What is the difference between build and new

I use new in almost all my controllers, but sometimes I have seen the build method inside the controllers of some apps. Can someone explain when should I use build?

John Smith wrote:

I use new in almost all my controllers, but sometimes I have seen the build method inside the controllers of some apps. Can someone explain when should I use build?

.build fixes the fact you cannot say this:

   my_post.tags.new(:name => 'reggae')

The new() operator is special, and your editor might color it different. So the architects of ActiveRecord use .build() instead.

Both create a new object. But shouldn't we just use this?

   my_post.tags.create(:name => 'reggae')    my_post.tags.create!(:name => 'reggae')

What do they do?

In particular, #build (and #create) automatically set, in this case, the :post_id of the associated Tag object to be my_post.id

There are times when you want to work briefly with an unsaved object and #build is more appropriate than #create

-Rob

Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com

build does not save the object. create does. if saving fails, create returns false, create! raises error (useful in migration, will rollback)

can #build support multiple nested models? like i have a 'Deal' with many 'Orders' and an 'Order' with many 'Duties'. all three need to created inside the Deal Controller.

Regards

You have to have a saved model object in order to use #build or it can't assign the post_id to the new Tag (or in your case, the deal_id on the order or the order_id to the duty). If you need to save them all at the "same time" you'll have to use a transaction and link them up yourself. (Warning: this pseudo-code is just off the top of my head; you'll need tests!)

@deal = Deal.new(...) @order = Order.new(...) @duty = Duty.new(...)

if everything_is_valid?    Duty.transaction do      Order.transaction do        Deal.transaction do          if @deal.save            @deal.orders << @order            if @order.save              @order.duties << @duty              if @duty.save                # Great!              else                # recover from unsavable duty (or use save!)              end            else              # recover from unsavable order (or use save!)            end          else            # recover from unsavable deal (or use save!)          end        end      end    end else    # complain about the invalid parts end

-Rob

Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com

You have to have a saved model object in order to use #build or it
can't assign the post_id to the new Tag (or in your case, the deal_id
on the order or the order_id to the duty). If you need to save them
all at the "same time" you'll have to use a transaction and link them
up yourself.

i am using complex forms given in "Advanced Rails Recipes". its doing a good job in saving a deal with an order. but 2nd level of nesting with duties is not working. Is there a plugin out there that can handle multiple levels of model nesting?

(Warning: this pseudo-code is just off the top of my head; you'll need tests!)

@deal = Deal.new(...) @order = Order.new(...) @duty = Duty.new(...)

if everything_is_valid? Duty.transaction do Order.transaction do Deal.transaction do if @deal.save @deal.orders << @order if @order.save @order.duties << @duty if @duty.save # Great! else # recover from unsavable duty (or use save!) end else # recover from unsavable order (or use save!) end else # recover from unsavable deal (or use save!) end end end end else # complain about the invalid parts end

i think for the above code, i need to create virtual attributes inside the 'deal' and 'order' models. Can this be handled using a form_for @deal and using partials inside it or do i need to use the form_tag and create separate params for deal, order, duty?

Regards

Sahil

In particular, #build (and #create) automatically set, in this case, the :post_id of the associated Tag object to be my_post.id

There are times when you want to work briefly with an unsaved object and #build is more appropriate than #create

can #build support multiple nested models? like i have a 'Deal' with many 'Orders' and an 'Order' with many 'Duties'. all three need to created inside the Deal Controller.

Regards

You have to have a saved model object in order to use #build or it can't assign the post_id to the new Tag (or in your case, the deal_id on the order or the order_id to the duty). If you need to save them all at the "same time" you'll have to use a transaction and link them up yourself. (Warning: this pseudo-code is just off the top of my head; you'll need tests!)

Actually build does handle being called on unsaved objects (it didn't
used to on has many through but that was the exception):

>> new_user = User.new => #<User id: nil, name: nil, state: nil, created_at: nil, updated_at:

>> post = new_user.posts.build => #<Post id: nil, user_id: nil, active: nil, created_at: nil,
updated_at: nil> >> comment = post.comments.build => #<Comment id: nil, post_id: nil, created_at: nil, updated_at: nil> >> new_user.save => true >> new_user => #<User id: 4, name: nil, state: nil, created_at: "2009-02-16
16:17:35", updated_at: "2009-02-16 16:17:35"> >> post => #<Post id: 4, user_id: 4, active: nil, created_at: "2009-02-16
16:17:35", updated_at: "2009-02-16 16:17:35"> >> comment => #<Comment id: 1, post_id: 4, created_at: "2009-02-16 16:17:35",
updated_at: "2009-02-16 16:17:35">

Fred