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.
John S. (Guest)
on 2009-02-14 21: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?
Phlip (Guest)
on 2009-02-14 21:38
(Received via mailing list)
John S. 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
Rob B. (Guest)
on 2009-02-14 22: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 B.    http://agileconsultingllc.com
removed_email_address@domain.invalid
DarkTatka (Guest)
on 2009-02-15 01: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)
Sahil D. (Guest)
on 2009-02-15 14:14
(Received via mailing list)
On Feb 15, 1:26 am, Rob B. <removed_email_address@domain.invalid>
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
Rob B. (Guest)
on 2009-02-15 22:28
(Received via mailing list)
On Feb 15, 2009, at 7:13 AM, Sahil D. 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 B.    http://agileconsultingllc.com
removed_email_address@domain.invalid
Sahil D. (Guest)
on 2009-02-16 08:10
(Received via mailing list)
On Feb 16, 1:27 am, Rob B. <removed_email_address@domain.invalid>
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
Frederick C. (Guest)
on 2009-02-16 18:19
(Received via mailing list)
On 15 Feb 2009, at 20:27, Rob B. 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.