Build vs new w Rails 3

W Rails 3 docs, metoda build dla asocjacji jest opisana jako taka sama jak Metoda new, ale z automatycznym przypisaniem klucza obcego. Prosto z docs:

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

Czytałem podobne gdzie indziej.

Jednak, gdy używam new (np. some_firm.clients.new bez żadnych parametrów), nowe skojarzenie firm_id jest automatycznie tworzone. Właśnie patrzę na wyniki w konsoli!

Czy coś przeoczyłem? Są dokumenty trochę nieaktualne (mało prawdopodobne)? Jaka jest różnica między build A new?

Author: ClosureCowboy, 2011-02-10

5 answers

Trochę źle odczytujesz dokumenty. some_firm.client.new tworzy nowy obiekt Client z kolekcji clients, dzięki czemu może automatycznie ustawić firm_id na some_firm.id, podczas gdy docs wywołują Client.new, który nie ma wiedzy o identyfikatorze żadnej firmy, więc potrzebuje firm_id przekazanego do niego.

Jedyna różnica pomiędzy some_firm.clients.new i some_firm.clients.build wydaje się być taka, że build dodaje również nowo utworzonego klienta do kolekcji clients:

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

Jeśli tworzysz obiekt poprzez skojarzenie, build powinien być preferowany niż new, ponieważ build utrzymuje obiekt w pamięci, some_firm (w tym przypadku) w spójnym stanie, nawet zanim jakiekolwiek obiekty zostaną zapisane w bazie danych.

 202
Author: henrym,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-14 06:59:59

build jest tylko aliasem dla new:

alias build new

Pełny kod można znaleźć: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb

 87
Author: Hatem Mahmoud,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-29 12:25:02

Masz rację, funkcje build i new mają ten sam efekt ustawiania klucza obcego, gdy są wywoływane przez skojarzenie. Wierzę, że powodem, dla którego dokumentacja jest napisana w ten sposób, jest wyjaśnienie, że nowy obiekt klienta jest inicjowany, w przeciwieństwie do nowej relacji active record. Jest to ten sam efekt, co wywołanie .nowy na zajęciach będzie w Ruby. To znaczy, że dokumentacja wyjaśnia, że wywołanie build on a association jest tym samym tworzenie nowego obiektu (wywołanie .nowy) i przekazanie kluczy obcych do tego obiektu. Wszystkie te polecenia są równoważne:

Firm.first.clients.build
Firm.first.clients.new
Client.new(:firm_id => Firm.first.id)
Wierzę w powód .build istnieje to firma.najpierw.klientów.new może być interpretowane w ten sposób, że tworzysz nowy obiekt relacji has_many, a nie rzeczywisty klient, więc wywołujesz .budowanie jest sposobem na wyjaśnienie tego.
 11
Author: Pan Thomakos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-10 07:29:29

Build vs new:

W większości new I build są takie same, ale build przechowuje obiekt w pamięci,

Np.

Dla nowego:

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

Dla budowy:

Firm.first.clients.build

Tutaj klienci są zapisywani w pamięci, przy zapisie firmowym zapisywane są również powiązane rekordy.

 3
Author: Sarwan Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-29 12:22:43

Model.Nowy

Tag.new post_id: 1 spowoduje utworzenie znacznika z jego zestawem post_id.

@ model.modelki.Nowy

@post.tags.build robi to samo i instancyjny znacznik będzie w @post.tags, zanim zostanie zapisany.

Oznacza to, że @post.save zapisze zarówno @post, jak i nowo zbudowany znacznik(zakładając, że ustawiono :inverse_of). Jest to świetne, ponieważ Rails sprawdzi oba obiekty przed zapisaniem i żaden z nich nie zostanie zapisany, jeśli któryś z nich nie powiedzie się walidacji.

Modele.nowy vs modelki.build

@post.tags.build i @post.tags.new są równoważne (przynajmniej od Rails 3.2).

 2
Author: tybro0103,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-03 18:51:04