Build vs new in Rails 3

Ruby on-RailsRuby on-Rails-3Associations

Ruby on-Rails Problem Overview


In the Rails 3 docs, the build method for associations is described as being the same as the new method, but with the automatic assignment of the foreign key. Straight from the docs:

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

I've read similar elsewhere.

However, when I use new (e.g. some_firm.clients.new without any parameters), the new client's firm_id association is automatically created. I'm staring at the results right now in the console!

Am I missing something? Are the docs a bit out of date (unlikely)? What's the difference between build and new?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

You're misreading the docs slightly. some_firm.client.new is creating a new Client object from the clients collection, and so it can automatically set the firm_id to some_firm.id, whereas the docs are calling Client.new which has no knowledge of any Firm's id at all, so it needs the firm_id passed to it.

The only difference between some_firm.clients.new and some_firm.clients.build seems to be that build also adds the newly-created client to the clients collection:

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

If you're creating an object through an association, build should be preferred over new as build keeps your in-memory object, some_firm (in this case) in a consistent state even before any objects have been saved to the database.

Solution 2 - Ruby on-Rails

build is just an alias for new:

alias build new

Full code can be found: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb#L74

Solution 3 - Ruby on-Rails

You are correct, the build and new functions have the same effect of setting the foreign key, when they are called through an association. I believe the reason the documentation is written like this is to clarify that a new Client object is being instantiated, as opposed to a new active record relationship. This is the same effect that calling .new on a class would have in Ruby. That is to say that the documentation is clarifying that calling build on an association is the same is creating a new object (calling .new) and passing the foreign keys to that object. These commands are all equivalent:

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

I believe the reason .build exists is that Firm.first.clients.new might be interpreted to mean that you are creating a new has_many relationship object, rather than an actual client, so calling .build is a way of clarifying this.

Solution 4 - Ruby on-Rails

build vs new:

> mostly new and build are same but build stores object in memory,

eg:

for new:

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

For build:

Firm.first.clients.build

Here clients are stored in memory, when save firm , associated records are also saved.

Solution 5 - Ruby on-Rails

Model.new

Tag.new post_id: 1 will instantiate a Tag with its post_id set.

@model.models.new

@post.tags.build does the same AND the instantiated Tag will be in @post.tags even before it's saved.

This means @post.save will save both the @post and the newly built tag (assuming :inverse_of is set). This is great because Rails will validate both objects before saving, and neither will be saved if either one of them fails validation.

models.new vs models.build

@post.tags.build and @post.tags.new are equivalent (at least since Rails 3.2).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionClosureCowboyView Question on Stackoverflow
Solution 1 - Ruby on-RailshenrymView Answer on Stackoverflow
Solution 2 - Ruby on-RailsHatem MahmoudView Answer on Stackoverflow
Solution 3 - Ruby on-RailsPan ThomakosView Answer on Stackoverflow
Solution 4 - Ruby on-RailsSarwan KumarView Answer on Stackoverflow
Solution 5 - Ruby on-Railstybro0103View Answer on Stackoverflow