ทับทิมบนราง. ฉันจะใช้วิธีการสร้างเรกคอร์ด. Active ใน a: เป็นของความสัมพันธ์ได้อย่างไร


128

ฉันไม่พบเอกสารใด ๆ เกี่ยวกับวิธีการสร้างใน Rails (ขณะนี้ฉันใช้ 2.0.2)

ดูเหมือนว่าคุณสามารถใช้วิธีการสร้างเพื่อเพิ่มระเบียนลงในhas_manyความสัมพันธ์ก่อนที่จะบันทึกระเบียนใดก็ได้

ตัวอย่างเช่น:

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

สิ่งนี้จะช่วยทั้งสุนัขและแท็กด้วยปุ่มต่างประเทศอย่างเหมาะสม สิ่งนี้ดูเหมือนจะไม่ทำงานในbelongs_toความสัมพันธ์

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

ฉันได้ลองแล้ว

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

Dogไม่ได้ตั้งค่าคีย์ต่างประเทศในกรณีนี้เนื่องจากในขณะนั้นถูกบันทึกบุคคลใหม่จะไม่มีรหัสเนื่องจากยังไม่ได้บันทึก

คำถามของฉันคือ:

  1. การสร้างจะทำงานอย่างไรเพื่อให้ Rails ฉลาดพอที่จะคิดวิธีบันทึกบันทึกในลำดับที่ถูกต้อง

  2. ฉันจะทำสิ่งเดียวกันในbelongs_toความสัมพันธ์ได้อย่างไร

  3. ฉันจะหาเอกสารเกี่ยวกับวิธีนี้ได้ที่ไหน

ขอบคุณ


เกี่ยวกับเอกสารดูที่คู่มือการรถไฟ"วิธีการที่เพิ่มขึ้นโดยbelongs_to"และ"วิธีการที่เพิ่มขึ้นโดยhas_one " เอกสารทางเทคนิคเพิ่มเติมสามารถพบได้ในเอกสาร API: และbelongs_to has_one
Dennis

คำตอบ:


147

บันทึกไว้ที่ไหน:

จากเอกสารประกอบ API ภายใต้การเชื่อมโยง has_many ใน " Module ActiveRecord :: Associations :: ClassMethods "

collection.build (attribute = {}, ... ) ส่งคืนออบเจคต์ใหม่หนึ่งชิ้นหรือมากกว่าของประเภทคอลเลกชันที่สร้างอินสแตนซ์ของแอททริบิวต์และเชื่อมโยงกับออบเจ็กต์นี้ผ่านคีย์ต่างประเทศ แต่ยังไม่ได้บันทึก หมายเหตุ: ใช้งานได้เฉพาะเมื่อมีวัตถุที่เชื่อมโยงอยู่แล้วเท่านั้นไม่ใช่วัตถุ!

คำตอบของการสร้างในทิศทางตรงกันข้ามคือไวยากรณ์ที่เปลี่ยนแปลงเล็กน้อย ในตัวอย่างของคุณกับสุนัข

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")

หรือแม้กระทั่ง

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

นอกจากนี้คุณยังสามารถใช้ create_dog เพื่อบันทึกทันที (คล้ายกับวิธี "สร้าง" ที่คุณสามารถโทรหาคอลเลกชันได้)

รางรถไฟฉลาดแค่ไหน มันวิเศษ (หรือมากกว่านั้นอย่างแม่นยำฉันไม่รู้จะรักที่จะรู้!)


4
@BushyMark: ใช้ method_missing หรือ metaporgramming เพื่อเพิ่มวิธีการเหล่านั้นด้วย define_method
Federico

@Federico วิธีการที่กำหนดหายไปที่ไหน?
awilkening

1
@ alock27 เช่นเดียวกับที่ ActiveRecord ใช้วิธีที่ขาดหายไปสำหรับคุณfind_by_emailและfind_by_column_nameวิธีการ มันจะแปลงวิธีการที่คุณส่งผ่านไปยังสตริงและแยกมันและพยายามที่จะจับคู่กับชื่อคอลัมน์ของตารางของคุณ
bigpotato

@edmund ขอบคุณสำหรับความคิดเห็นของคุณ เพื่อความชัดเจนฉันเข้าใจว่า method_missing ทำงานอย่างไร ฉันพยายามค้นหาตำแหน่งจริงของไฟล์ที่กำหนดวิธีการเฉพาะนี้ที่ขาดหายไป
awilkening

@ alock27 ถ้าคุณถามเพราะคุณต้องการดูว่ามันถูกกำหนดอย่างไรคุณควรตรวจสอบ Metaprogramming Ruby แต่ถ้าคุณกำลังมองหาที่ตั้งจริง ๆ คุณอาจใช้ Google กับซอร์สโค้ดก็ได้
MCB

48
@article = user.articles.build(:title => "MainTitle")
@article.save

>> d.tags.build (: number => "123456") >> d.save # => true ไม่เหมือนกันใช่ไหม
antiqe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.