Bangun vs baru di Rails 3

125

Dalam Rails 3 docs , buildmetode untuk asosiasi digambarkan sama dengan newmetode, tetapi dengan penugasan otomatis kunci asing. Langsung dari dokumen:

Firm#clients.build (similar to Client.new("firm_id" => id))

Saya sudah membaca yang serupa di tempat lain.

Namun, ketika saya menggunakan new(misalnya some_firm.clients.newtanpa parameter), klien baru firm_idasosiasi yang otomatis dibuat. Saya sedang menatap hasil sekarang di konsol!

Apakah saya melewatkan sesuatu? Apakah dokumennya sedikit ketinggalan zaman (tidak mungkin)? Apa perbedaan antara builddan new?

ClosureCowboy
sumber
3
Orang yang mencari jawaban cepat, periksa jawaban ke-2: "build" hanyalah alias untuk "baru"
ivanreese

Jawaban:

208

Anda sedikit salah membaca dokumen. some_firm.client.newadalah menciptakan baru Clientobjek dari koleksi klien, dan sehingga secara otomatis dapat mengatur firm_iduntuk some_firm.id, sedangkan docs panggil Client.newyang tidak memiliki pengetahuan tentang id setiap Firm sama sekali, sehingga membutuhkan firm_idberlalu untuk itu.

Satu-satunya perbedaan antara some_firm.clients.newdan some_firm.clients.buildsepertinya itu buildjuga menambahkan klien yang baru dibuat ke clientskoleksi:

henrym:~/testapp$ rails c
Loading development environment (Rails 3.0.4)
r:001 > (some_firm = Firm.new).save # Create and save a new Firm
#=> true 
r:002 > some_firm.clients           # No clients yet
#=> [] 
r:003 > some_firm.clients.new       # Create a new client
#=> #<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil> 
r:004 > some_firm.clients           # Still no clients
#=> [] 
r:005 > some_firm.clients.build     # Create a new client with build
#=> #<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil> 
r:006 > some_firm.clients           # New client is added to clients 
#=> [#<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil>] 
r:007 > some_firm.save
#=> true 
r:008 > some_firm.clients           # Saving firm also saves the attached client
#=> [#<Client id: 1, firm_id: 1, created_at: "2011-02-11 00:18:47",
updated_at: "2011-02-11 00:18:47">] 

Jika Anda membuat objek melalui asosiasi, buildsebaiknya lebih disukai newkarena build menyimpan objek di-memori Anda, some_firm(dalam hal ini) dalam keadaan konsisten bahkan sebelum benda apa pun disimpan ke database.

henrym
sumber
8
Menggunakan some_firm.client.newjuga menambahkan klien untuk some_firm.clients, dan memanggil savedi some_firmmengakibatkan kesalahan validasi menunjukkan bahwa clienttidak sah. Jika keduanya newdan buildmenambahkan klien baru ke some_firmkoleksi klien, apa buildyang newtidak dilakukan? Saya minta maaf karena padat, di sini!
ClosureCowboy
1
+1 Saya menerima hasil Anda dengan 3.0.4. Saya akan senang jika seseorang dengan 3.0.3 dapat mengkonfirmasi bahwa saya tidak gila.
ClosureCowboy
41
@henrym Sepertinya di 3.2.6 clients.new dan clients.build serupa di keduanya menambahkan objek baru ke dalam koleksi. Saya ingin menambahkan komentar untuk siapa saja yang menemukan ini sementara Googling seperti saya
hubbard
11
Sepertinya tidak ada perbedaan di antara mereka di Rails 3.2.3
Aditya Kapoor
4
Jawaban ini tidak benar untuk Rails> 3.2.13, di mana 'build' hanyalah alias untuk 'baru'. Lihat jawaban @ HatemMahmoud di bawah ini.
Andreas
91

buildhanyalah alias untuk new:

alias build new

Kode lengkap dapat ditemukan: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb#L74

Hatem Mahmoud
sumber
13
alias build newpada rail 3.2.13
fontno
7
Ini hanya berlaku untuk beberapa asosiasi / hubungan. Asosiasi tunggal, misalnya, memiliki definisi yang sepenuhnya berbeda untuk builddan build_#{association}. Lihat di sini dan di sini .
coreyward
1
Apakah ini masih berlaku untuk Rails 4?
fatman13
1
di sini adalah laporan bug ... yang menunjukkan jika Anda menggunakan baru seperti restaurant.customers.new, sebagai cara untuk mendapatkan pelanggan baru yang terkait dengan restoran tanpa menambahkannya ke restaurant.customers, untuk menggunakan scoped ... seperti restoran .customers.scoped.new
user3334690
11

Anda benar, build dan fungsi-fungsi baru memiliki efek yang sama dengan pengaturan kunci asing, ketika mereka dipanggil melalui asosiasi. Saya percaya alasan dokumentasi ditulis seperti ini adalah untuk mengklarifikasi bahwa objek Klien baru sedang dipakai, sebagai lawan dari hubungan rekaman aktif baru. Ini adalah efek yang sama yang memanggil. Baru di kelas akan memiliki di Ruby. Dengan kata lain, dokumentasinya mengklarifikasi bahwa memanggil build pada asosiasi adalah sama dengan membuat objek baru (memanggil .new) dan meneruskan kunci asing ke objek tersebut. Semua perintah ini setara:

Firm.first.clients.build
Firm.first.clients.new
Client.new(:firm_id => Firm.first.id)

Saya percaya alasan .build ada adalah bahwa Firm.first.clients.new mungkin diartikan berarti bahwa Anda membuat objek hubungan has_many baru, daripada klien yang sebenarnya, jadi memanggil .build adalah cara untuk menjelaskan hal ini.

Pan Thomakos
sumber
Jadi mereka adalah setara. Jelas itu kelihatannya. Terima kasih!
ClosureCowboy
5
Ini tidak benar. Dua yang pertama adalah setara dalam versi Rails yang lebih baru (sepertinya pada saat mempostingnya bukan). TETAPI, yang terakhir memiliki perbedaan signifikan di Firm.first.clients itu tidak akan berisi klien baru.
tybro0103
4

buildvs new:

kebanyakan baru dan build sama tetapi build menyimpan objek dalam memori ,

misalnya:

untuk yang baru:

Client.new(:firm_id=>Firm.first.id)

Untuk membangun:

Firm.first.clients.build

Di sini klien disimpan dalam memori, ketika menyimpan perusahaan, catatan terkait juga disimpan.

Sarwan Kumar
sumber
2

Model. Baru

Tag.new post_id: 1akan instantiate Tag dengan post_idset -nya .

@ model.models.new

@post.tags.buildapakah tag yang sama DAN yang dipakai akan berada di @post.tagsbahkan sebelum itu disimpan.

Ini berarti @post.saveakan menyimpan @post dan tag yang baru dibangun (dengan asumsi: inverse_of diatur). Ini bagus karena Rails akan memvalidasi kedua objek sebelum disimpan, dan tidak ada yang akan disimpan jika salah satu dari mereka gagal validasi.

models.new vs models.build

@post.tags.builddan @post.tags.newsetara (setidaknya sejak Rails 3.2).

tybro0103
sumber
bagaimana dengan ini The only difference between some_firm.clients.new and some_firm.clients.build seems to be that build also adds the newly-created client to the clients collection:?
ア レ ッ ク ス