Ruby on Rails. Jak używać metody .build modułu aktywnego rekordu w: należy do relacji?

130

Nie mogłem znaleźć żadnej dokumentacji na temat metody .build w Railsach (obecnie używam 2.0.2).

Wydaje się, że dzięki eksperymentom można użyć metody budowania, aby dodać rekord do has_manyrelacji, zanim którykolwiek z nich zostanie zapisany.

Na przykład:

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

Pozwoli to poprawnie zapisać zarówno psa, jak i tag z kluczami obcymi. To nie wydaje się działać w belongs_tozwiązku.

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

Ja też próbowałem

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

Klucz obcy Dogw tym przypadku nie jest ustawiony ze względu na fakt, że w momencie jego zapisywania nowa osoba nie ma identyfikatora, ponieważ nie został on jeszcze zapisany.

Moje pytania to:

  1. Jak działa kompilacja, aby Railsy były wystarczająco sprytne, aby dowiedzieć się, jak zapisać rekordy we właściwej kolejności?

  2. Jak mogę zrobić to samo w belongs_tozwiązku?

  3. Gdzie mogę znaleźć dokumentację dotyczącą tej metody?

Dziękuję Ci

gwiezdny
źródło
Jeśli chodzi o dokumentację, zobacz Przewodniki po Railsach „Metody dodane przez belongs_to i „Metody dodane przez has_one . Więcej dokumentacji technicznej można znaleźć w dokumentacji API: belongs_toi has_one.
Dennis

Odpowiedzi:

148

Gdzie jest to udokumentowane:

Z dokumentacji API pod asocjacją has_many w „ Module ActiveRecord :: Associations :: ClassMethods

collection.build (attributes = {},…) Zwraca jeden lub więcej nowych obiektów typu kolekcji, dla których utworzono wystąpienie z atrybutami i połączono z tym obiektem za pomocą klucza obcego, ale nie zostały jeszcze zapisane. Uwaga: Działa to tylko wtedy, gdy powiązany obiekt już istnieje, a nie jeśli jest zerowy!

Odpowiedzią na budowanie w przeciwnym kierunku jest nieco zmieniona składnia. W swoim przykładzie z psami

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

lub nawet

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

Możesz także użyć create_dog, aby zapisać go natychmiast (podobnie jak odpowiednia metoda "create", którą możesz wywołać w kolekcji)

Dlaczego szyny są wystarczająco inteligentne? To magia (a dokładniej, po prostu nie wiem, chciałbym się dowiedzieć!)

BushyMark
źródło
4
@BushyMark: używa metody method_missing lub metaporgramming, aby dodać te metody za pomocą define_method.
Federico,
@Federico gdzie brakuje zdefiniowanej metody?
awilkening
1
@ alock27 To samo, co sposób, w jaki ActiveRecord używa metody brakującej dla twoich find_by_emaili find_by_column_namemetod. Konwertuje przekazaną metodę na łańcuch, analizuje ją i próbuje dopasować do nazw kolumn tabeli.
bigpotato
@edmund Dzięki za komentarz. Żeby było jasne, rozumiem, jak działa brakująca_metoda. Próbowałem zlokalizować rzeczywistą lokalizację pliku, który definiuje tę konkretną metodę, której brakuje.
otwarcie
@ alock27, jeśli pytasz, ponieważ chcesz zobaczyć, jak jest zdefiniowany, powinieneś sprawdzić Metaprogramowanie Rubiego. Ale jeśli naprawdę szukasz rzeczywistej lokalizacji, prawdopodobnie możesz wygooglować kod źródłowy.
MCB,
49
@article = user.articles.build(:title => "MainTitle")
@article.save
nehpets
źródło
>> d.tags.build (: number => "123456") >> d.save # => true To nie to samo?
antiqe