Ruby on Rails. Wie verwende ich die Active Record .build-Methode in einer: gehört zur Beziehung?

128

Ich konnte keine Dokumentation zur .build-Methode in Rails finden (ich verwende derzeit 2.0.2).

Durch Experimentieren können Sie anscheinend die Erstellungsmethode verwenden, um einen Datensatz zu einer has_manyBeziehung hinzuzufügen, bevor einer der Datensätze gespeichert wurde.

Beispielsweise:

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

Dadurch werden sowohl der Hund als auch die Markierung mit den Fremdschlüsseln ordnungsgemäß gespeichert. Dies scheint in einer belongs_toBeziehung nicht zu funktionieren .

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

Ich habe es auch versucht

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

Der Fremdschlüssel Dogwird in diesem Fall nicht festgelegt, da die neue Person zum Zeitpunkt des Speicherns keine ID hat, da er noch nicht gespeichert wurde.

Meine Fragen sind:

  1. Wie funktioniert Build, damit Rails intelligent genug ist, um herauszufinden, wie die Datensätze in der richtigen Reihenfolge gespeichert werden können?

  2. Wie kann ich in einer belongs_toBeziehung dasselbe tun ?

  3. Wo finde ich Dokumentation zu dieser Methode?

Danke dir

stellard
quelle
Informationen zur Dokumentation finden Sie in den Rails-Handbüchern "Methoden hinzugefügt von belongs_to" und "Methoden hinzugefügt von has_one" . Weitere technische Dokumentationen finden Sie in den API-Dokumenten: belongs_tound has_one.
Dennis

Antworten:

147

Wo es dokumentiert ist:

Aus der API-Dokumentation unter der Zuordnung has_many in " Module ActiveRecord :: Associations :: ClassMethods "

collection.build (attribute = {},…) Gibt ein oder mehrere neue Objekte des Sammlungstyps zurück, die mit Attributen instanziiert und über einen Fremdschlüssel mit diesem Objekt verknüpft wurden, aber noch nicht gespeichert wurden. Hinweis: Dies funktioniert nur, wenn ein zugeordnetes Objekt bereits vorhanden ist, nicht wenn es Null ist!

Die Antwort auf das Bauen in die entgegengesetzte Richtung ist eine leicht veränderte Syntax. In Ihrem Beispiel mit den Hunden,

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

oder auch

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

Sie können auch create_dog verwenden, um es sofort zu speichern (ähnlich wie die entsprechende "create" -Methode, die Sie für die Sammlung aufrufen können).

Wie sind Schienen klug genug? Es ist Magie (oder genauer gesagt, ich weiß es einfach nicht, würde es gerne herausfinden!)

BushyMark
quelle
4
@BushyMark: Es verwendet method_missing oder metaporgramming, um diese Methoden mit define_method hinzuzufügen.
Federico
@Federico wo ist die fehlende Methode definiert?
Erwachen
1
@ alock27 Entspricht der Verwendung der Methode, die ActiveRecord für Ihre find_by_emailund find_by_column_nameMethoden fehlt . Es konvertiert die Methode, die Sie übergeben, in eine Zeichenfolge, zerlegt sie und versucht, sie mit den Spaltennamen Ihrer Tabelle abzugleichen.
Bigpotato
@edmund Danke für deinen Kommentar. Um es klar zu sagen, ich verstehe, wie method_missing funktioniert. Ich habe versucht, den tatsächlichen Speicherort der Datei zu finden, in der diese bestimmte fehlende Methode definiert ist.
Erwachen
@ alock27 Wenn Sie fragen, weil Sie untersuchen möchten, wie es definiert ist, sollten Sie sich Metaprogramming Ruby ansehen. Wenn Sie jedoch wirklich nach dem tatsächlichen Standort suchen, können Sie wahrscheinlich den Quellcode bei Google suchen.
MCB
48
@article = user.articles.build(:title => "MainTitle")
@article.save
Nehpets
quelle
>> d.tags.build (: number => "123456") >> d.save # => true Nicht dasselbe?
Antiqe