Forum: Ruby on Rails What is the difference between build and new

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
71e53b54803415f87ef1b898baf8f3ca?d=identicon&s=25 John Smith (terry_wolf)
on 2009-02-14 20:21
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?
Aafa8848c4b764f080b1b31a51eab73d?d=identicon&s=25 Phlip (Guest)
on 2009-02-14 20:38
(Received via mailing list)
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?

--
   Phlip
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2009-02-14 21:27
(Received via mailing list)
On Feb 14, 2009, at 2:37 PM, Phlip wrote:
> The new() operator is special, and your editor might color it
> --
>   Phlip


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
43ebaaf048f056d599a7218f834179ef?d=identicon&s=25 DarkTatka (Guest)
on 2009-02-15 00:17
(Received via mailing list)
build does not save the object. create does. if saving fails, create
returns false, create! raises error (useful in migration, will
rollback)
8d295740bdc6fecc406cff2e8b895f48?d=identicon&s=25 Sahil Dave (Guest)
on 2009-02-15 13:14
(Received via mailing list)
On Feb 15, 1:26 am, Rob Biedenharn <R...@AgileConsultingLLC.com>
wrote:
>
>
> 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
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2009-02-15 21:28
(Received via mailing list)
On Feb 15, 2009, at 7:13 AM, Sahil Dave wrote:
> 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
8d295740bdc6fecc406cff2e8b895f48?d=identicon&s=25 Sahil Dave (Guest)
on 2009-02-16 07:10
(Received via mailing list)
On Feb 16, 1:27 am, Rob Biedenharn <R...@AgileConsultingLLC.com>
wrote:
>
> 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?

>          if @deal.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
81b61875e41eaa58887543635d556fca?d=identicon&s=25 Frederick Cheung (Guest)
on 2009-02-16 17:19
(Received via mailing list)
On 15 Feb 2009, at 20:27, Rob Biedenharn wrote:

>> can #build support multiple nested models? like i have a 'Deal' with
> 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:
nil>
 >> 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
This topic is locked and can not be replied to.