Ruby on Rails. Bagaimana cara menggunakan metode .build Rekaman Aktif dalam: milik hubungan?

128

Saya belum dapat menemukan dokumentasi apa pun tentang metode .build di Rails (saat ini saya menggunakan 2.0.2).

Melalui eksperimen, tampaknya Anda dapat menggunakan metode build untuk menambahkan catatan ke dalam suatu has_manyhubungan sebelum salah satu catatan disimpan.

Sebagai contoh:

class Dog < ActiveRecord::Base
  has_many :tags
  belongs_to :person
end

class Person < ActiveRecord::Base
  has_many :dogs
end

# rails c
d = Dog.new
d.tags.build(:number => "123456")
d.save # => true

Ini akan menyimpan anjing dan tag dengan kunci asing dengan benar. Ini sepertinya tidak berhasil dalam suatu belongs_tohubungan.

d = Dog.new
d.person.build # => nil object on nil.build

Saya juga sudah mencoba

d = Dog.new
d.person = Person.new
d.save # => true

Kunci asing masuk Dogtidak diatur dalam kasus ini karena fakta bahwa pada saat disimpan, orang baru tidak memiliki id karena belum disimpan.

Pertanyaan saya adalah:

  1. Bagaimana cara membangun agar Rails cukup pintar untuk mengetahui cara menyimpan catatan dalam urutan yang benar?

  2. Bagaimana saya bisa melakukan hal yang sama dalam suatu belongs_tohubungan?

  3. Di mana saya dapat menemukan dokumentasi tentang metode ini?

Terima kasih

Stellard
sumber
Mengenai dokumentasi, lihat Panduan Rails "Metode ditambahkan oleh belongs_to" dan "Metode Ditambahkan oleh has_one" . Lebih banyak dokumentasi teknis dapat ditemukan di dokumen API: belongs_toand has_one.
Dennis

Jawaban:

147

Di mana itu didokumentasikan:

Dari dokumentasi API di bawah asosiasi has_many di " Module ActiveRecord :: Associations :: ClassMethods "

collection.build (atribut = {}, ...) Mengembalikan satu atau lebih objek baru dari tipe koleksi yang telah dipakai dengan atribut dan ditautkan ke objek ini melalui kunci asing, tetapi belum disimpan. Catatan: Ini hanya berfungsi jika objek terkait sudah ada, bukan jika nihil!

Jawaban untuk membangun di arah yang berlawanan adalah sintaks yang sedikit diubah. Dalam contoh Anda dengan anjing-anjing,

Class Dog
   has_many :tags
   belongs_to :person
end

Class Person
  has_many :dogs
end

d = Dog.new
d.build_person(:attributes => "go", :here => "like normal")

atau bahkan

t = Tag.new
t.build_dog(:name => "Rover", :breed => "Maltese")

Anda juga dapat menggunakan create_dog untuk menyimpannya secara instan (seperti metode "buat" yang sesuai yang dapat Anda panggil di koleksi)

Bagaimana rel cukup pintar? Ini sihir (atau lebih tepatnya, saya tidak tahu, akan senang mengetahuinya!)

BushyMark
sumber
4
@BushyMark: ia menggunakan method_missing atau metaporgramming untuk menambahkan metode-metode tersebut dengan define_method.
Federico
@ Federico di mana metode yang hilang didefinisikan?
awilkening
1
@ alock27 Sama seperti cara ActiveRecord menggunakan metode yang hilang untuk Anda find_by_emaildan find_by_column_namemetode. Ini mengonversi metode yang Anda berikan ke string dan membedahnya dan mencoba mencocokkannya dengan nama kolom tabel Anda.
bigpotato
@ Edmund Terima kasih atas komentar Anda. Agar jelas, saya mengerti cara kerja method_missing. Saya mencoba mencari lokasi sebenarnya dari file yang mendefinisikan metode khusus ini hilang.
Membangunkan
@ alock27 jika Anda bertanya karena Anda ingin melihat bagaimana itu didefinisikan Anda harus memeriksa Metaprogramming Ruby. Tetapi jika Anda benar-benar mencari lokasi sebenarnya, Anda mungkin dapat Google untuk kode sumber.
MCB
48
@article = user.articles.build(:title => "MainTitle")
@article.save
nehpets
sumber
>> d.tags.build (: number => "123456") >> d.save # => true Tidak sama?
antiqe