Differences in rails between new + save and create

Ruby on-RailsRuby on-Rails-3

Ruby on-Rails Problem Overview


I'm new to rails and I don't understand the differences between the use of new+save methods and the create method.

def create
    @item = Item.new(params[:item])

    respond_to do |format|
      if @item.save
        format.html { redirect_to @item, notice: 'Item was successfully created.' }
        format.json { render json: @item, status: :created, location: @item }
      else
        format.html { render action: "new" }
        format.json { render json: @item.errors, status: :unprocessable_entity }
      end
    end
end

and:

  def create

    respond_to do |format|
      if Item.create(params[:item])
        format.html { redirect_to @item, notice: 'Item was successfully created.' }
        format.json { render json: @item, status: :created, location: @item }
      else
        format.html { render action: "new" }
        format.json { render json: @item.errors, status: :unprocessable_entity }
      end
    end
  end

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

Although it is correct that create calls new and then save there is a big difference between the two alternatives in their return values.

Save returns either true or false depending on whether the object was saved successfully to the database or not. This can then be used for flow control as per the first example in the question above.

Create will return the model regardless of whether the object was saved or not. This has implications for the code above in that the top branch of the if statement will always be executed even if the object fails validations and is not saved.

If you use create with branching logic you are at risk of silent failures which is not the case if you use new + save.

The create alternative can be useful in controllers where respond_with is used for API (JSON/XML) responses. In this case the existence of errors on the object will cause the errors to be returned in the response with a status of unprocessable_entity, which is exactly what you want from an API.

I would always use the new + save option for html, especially if you are relying on the return value for flow control.

Solution 2 - Ruby on-Rails

Internally create calls new then save anyway:

  def create(attributes = nil, options = {}, &block)
    if attributes.is_a?(Array)
      attributes.collect { |attr| create(attr, options, &block) }
    else
      object = new(attributes, options, &block)
      object.save
      object
    end
  end

Solution 3 - Ruby on-Rails

new creates the object but doesn't save it.

create creates the object and saves it, i.e. .new and .save

create! creates the object and tries to save it but raises an exception if validations fails, e.g. .new and .save!

One of confusion items is that the above is the actions that you take on an object, but similar names are also given to controller methods, especially in a RESTful environment. For example you have a create action.... which creates a new object, and then saves it and another create action which just does an object create.

If you're wondering "why create an object if I'm not going to save it?" consider this - the system 'tries' to save the object - but a validation prevents it and the user is asked to fill in more information on a form, perhaps required fields. One wants the object to still be created (.new) while this is going on and it will hold the values that have been assigned so far. However it doesn't actually get saved until it passes the validations as well.

Solution 4 - Ruby on-Rails

when you use, rails actually is creating the records but didn't save it, so in the process you can also assign smth

@item = Item.new(params[:item])

but when you use:

if Item.create(params[:item])
.....

it will immediately create and save

you can check it with rails c

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMatteo PagliazziView Question on Stackoverflow
Solution 1 - Ruby on-RailsnmottView Answer on Stackoverflow
Solution 2 - Ruby on-RailspjumbleView Answer on Stackoverflow
Solution 3 - Ruby on-RailsMichael DurrantView Answer on Stackoverflow
Solution 4 - Ruby on-RailsSaid KaldybaevView Answer on Stackoverflow