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