web-dev-qa-db-de.com

Build vs new in Rails 3

In der Rails 3 docs ist die build -Methode für Assoziationen dieselbe wie die new -Methode, jedoch mit die automatische Vergabe des Fremdschlüssels. Direkt aus den Dokumenten:

Firm#clients.build (similar to Client.new("firm_id" => id))

Ich habe an anderer Stelle ähnlich gelesen.

Wenn ich jedoch new verwende (z. B. some_firm.clients.new Ohne Parameter), lautet die firm_id - Zuordnung des neuen Clients automatisch erstellt. Ich starre gerade auf die Ergebnisse in der Konsole!

Vermisse ich etwas? Sind die Dokumente etwas veraltet (unwahrscheinlich)? Was ist der Unterschied zwischen build und new?

123
ClosureCowboy

Sie lesen die Dokumente leicht falsch. some_firm.client.new erstellt ein neues Client -Objekt aus der clients-Auflistung und kann daher den firm_id automatisch auf some_firm.id setzen, wohingegen dies für die Dokumente gilt Aufrufen von Client.new, von dem die ID einer Firma überhaupt nicht bekannt ist, daher muss der firm_id an diese Firma übergeben werden.

Der einzige Unterschied zwischen some_firm.clients.new und some_firm.clients.build scheint darin zu bestehen, dass build den neu erstellten Client ebenfalls zur clients-Auflistung hinzufügt:

henrym:~/testapp$ Rails c
Loading development environment (Rails 3.0.4)
r:001 > (some_firm = Firm.new).save # Create and save a new Firm
#=> true 
r:002 > some_firm.clients           # No clients yet
#=> [] 
r:003 > some_firm.clients.new       # Create a new client
#=> #<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil> 
r:004 > some_firm.clients           # Still no clients
#=> [] 
r:005 > some_firm.clients.build     # Create a new client with build
#=> #<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil> 
r:006 > some_firm.clients           # New client is added to clients 
#=> [#<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil>] 
r:007 > some_firm.save
#=> true 
r:008 > some_firm.clients           # Saving firm also saves the attached client
#=> [#<Client id: 1, firm_id: 1, created_at: "2011-02-11 00:18:47",
updated_at: "2011-02-11 00:18:47">] 

Wenn Sie ein Objekt über eine Assoziation erstellen, sollte buildnew vorgezogen werden, da build Ihr speicherinternes Objekt some_firm (in diesem Fall) in a behält konsistenter Zustand, noch bevor Objekte in der Datenbank gespeichert wurden.

207
henrym

build ist nur ein Alias ​​für new:

alias build new

Den vollständigen Code finden Sie hier: https://github.com/Rails/rails/blob/master/activerecord/lib/active_record/relation.rb#L74

89
Hatem Mahmoud

Sie haben Recht, der Build und die neuen Funktionen haben den gleichen Effekt wie das Setzen des Fremdschlüssels, wenn sie über eine Assoziation aufgerufen werden. Ich glaube, der Grund, warum die Dokumentation so geschrieben ist, ist zu verdeutlichen, dass ein neues Client-Objekt im Gegensatz zu einer neuen aktiven Datensatzbeziehung instanziiert wird. Dies ist der gleiche Effekt, den das Aufrufen von .new für eine Klasse in Ruby hätte. Das heißt, dass in der Dokumentation klargestellt wird, dass der Aufruf eines Assoziationsaufbaus der gleiche ist, wenn ein neues Objekt erstellt wird (Aufruf von .new) und die Fremdschlüssel an dieses Objekt übergeben werden. Diese Befehle sind alle gleichwertig:

Firm.first.clients.build
Firm.first.clients.new
Client.new(:firm_id => Firm.first.id)

Ich glaube, der Grund, warum .build existiert, ist, dass Firm.first.clients.new so interpretiert werden könnte, dass Sie ein neues has_many-Beziehungsobjekt erstellen, anstatt einen tatsächlichen Client.

11
Pan Thomakos

build vs new:

meistens sind new und build gleich, aber build speichert das Objekt im Speicher,

z.B:

für neue:

Client.new(:firm_id=>Firm.first.id)

Für den Bau:

Firm.first.clients.build

Hier werden Clients im Speicher abgelegt, bei fester Speicherung werden auch zugehörige Datensätze gespeichert.

4
Sarwan Kumar

Modell.neu

Tag.new post_id: 1 instanziiert ein Tag mit seinem post_id einstellen.

@ model.models.new

@post.tags.build macht dasselbe UND das instanziierte Tag befindet sich in @post.tags noch bevor es gespeichert ist.

Das heisst @post.save speichert sowohl das @post als auch das neu erstellte Tag (vorausgesetzt: inverse_of ist gesetzt). Dies ist großartig, da Rails beide Objekte vor dem Speichern validieren und keines von beiden gespeichert wird, wenn eines von beiden die Validierung nicht besteht.

models.new vs models.build

@post.tags.build und @post.tags.new sind gleichwertig (spätestens seit Rails 3.2).

2
tybro0103