Build vs new in Rails 3

前提是你 提交于 2019-12-17 01:37:08

问题


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?


回答1:


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.




回答2:


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




回答3:


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.




回答4:


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.




回答5:


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



来源:https://stackoverflow.com/questions/4954313/build-vs-new-in-rails-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!