Viên ngọc trên tay vịn. Làm cách nào để sử dụng phương thức Active Record .build trong: thuộc về mối quan hệ?


128

Tôi đã không thể tìm thấy bất kỳ tài liệu nào về phương thức .build trong Rails (tôi hiện đang sử dụng 2.0.2).

Thông qua thử nghiệm, có vẻ như bạn có thể sử dụng phương thức xây dựng để thêm bản ghi vào has_manymối quan hệ trước khi bản ghi được lưu.

Ví dụ:

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

Điều này sẽ lưu cả con chó và thẻ với các khóa ngoại đúng cách. Điều này dường như không hoạt động trong một belongs_tomối quan hệ.

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

Tôi cũng đã thử

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

Khóa ngoại Dogkhông được đặt trong trường hợp này do thực tế là tại thời điểm nó được lưu, người mới không có id vì chưa được lưu.

Câu hỏi của tôi là:

  1. Làm thế nào để xây dựng công việc sao cho Rails đủ thông minh để tìm ra cách lưu các bản ghi theo đúng thứ tự?

  2. Làm thế nào tôi có thể làm điều tương tự trong một belongs_tomối quan hệ?

  3. Tôi có thể tìm thấy bất kỳ tài liệu về phương pháp này ở đâu?

Cảm ơn bạn


Về tài liệu, xem Hướng dẫn Rails "Phương thức được thêm bởi belongs_to""Phương thức được thêm bởi has_one" . Nhiều tài liệu kỹ thuật có thể được tìm thấy trong các tài liệu API: belongs_tohas_one.
Dennis

Câu trả lời:


147

Tài liệu được ghi ở đâu:

Từ tài liệu API dưới liên kết has_many trong " Module ActiveRecord :: Associations :: ClassMethods "

bộ sưu tập.build (thuộc tính = {}, tập) Trả về một hoặc nhiều đối tượng mới của loại bộ sưu tập đã được khởi tạo với các thuộc tính và được liên kết với đối tượng này thông qua khóa ngoại, nhưng chưa được lưu. Lưu ý: Điều này chỉ hoạt động nếu một đối tượng liên quan đã tồn tại, không phải nếu nó không!

Câu trả lời cho việc xây dựng theo hướng ngược lại là một cú pháp thay đổi một chút. Trong ví dụ của bạn với những con chó,

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

hoặc thậm chí

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

Bạn cũng có thể sử dụng create_dog để lưu nó ngay lập tức (giống như phương thức "tạo" tương ứng mà bạn có thể gọi trên bộ sưu tập)

Làm thế nào là đường ray đủ thông minh? Đó là phép thuật (hay chính xác hơn, tôi chỉ không biết, rất thích tìm hiểu!)


4
@BushyMark: nó sử dụng phương thức_missing hoặc metaporgramming để thêm các phương thức đó với notify_method.
Federico

@Federico đâu là phương thức bị thiếu?
uống vào

1
@ alock27 Tương tự như cách ActiveRecord sử dụng phương thức bị thiếu cho phương thức find_by_emailfind_by_column_namephương thức của bạn . Nó chuyển đổi phương thức bạn truyền vào một chuỗi và phân tích nó và cố gắng khớp nó với tên cột của bảng.
bigpotato

@edmund Cảm ơn bình luận của bạn. Để rõ ràng, tôi hiểu cách hoạt động của phương thức. Tôi đã cố gắng xác định vị trí thực tế của tệp xác định phương thức cụ thể này bị thiếu.
awilkening

@ alock27 nếu bạn hỏi vì bạn muốn xem xét cách xác định, bạn nên kiểm tra Metaprogramming Ruby. Nhưng nếu bạn thực sự đang tìm kiếm vị trí thực tế, bạn có thể tìm kiếm mã nguồn.
MCB

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

>> d.tags.build (: number => "123456") >> d.save # => đúng Không giống nhau?
Antiqe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.