Victor
Victor

Reputation: 13378

Create or new in Rails controller in create action

In Rails, we define the create action 2 ways. What are the difference?

def create
  @shop = Shop.new(params[:shop])
  if @shop.save
    flash[:success] = 'Thanks for adding new shop.'
    redirect_to @shop
  else
    flash[:error] = 'Error adding review,  please try again.'
    redirect_to @shop
  end
end

# or

def create
  @shop = Shop.create(params[:shop])
  if @shop.save
    flash[:success] = 'Thanks for adding new shop.'
    redirect_to @shop
  else
    flash[:error] = 'Error adding review,  please try again.'
    redirect_to @shop
  end
end

Considering we already have:

def new
  @shop = Shop.new
end

Which is more proper?

Upvotes: 3

Views: 1221

Answers (4)

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230346

In create controller action, Shop.new is useless without following @shop.save. Usually it's being split into these two steps to handle validation errors. We init shop with data from the user. If data is ok, we save the shop. If there are validation errors, we tell user to try again.

Or we need to do some complex attribute initialisation before we save record to the database.

@user = User.new params[:user]
@user.reputation = fetch_reputation_from_stackoverflow

if @user.save
  # the usual steps here

RE: question edit

Considering we already have:

def new
  @shop = Shop.new
end

What is there in new action is completely irrelevant. If your validations might fail (or otherwise your model might not be created successfully), then use new + save pair. If you are sure that input data is ok and model will always save, then use only create (following save is redundant).

Upvotes: 1

sjain
sjain

Reputation: 23344

If you used Model.create, you don't need to save the object explicitly. The create method will do that for you. If you used Model.new, you need to save the object by doing @object.save. The new method does not do that for you.

Using Model.new:

def create
  @shop = Shop.new(params[:shop])
   if @shop.save
    flash[:success] = 'Thanks for adding new shop.'
    redirect_to @shop
  else
    flash[:error] = 'Error adding review,  please try again.'
    redirect_to @shop
  end
end

Using Model.create:

def create
  @shop = Shop.create(params[:shop])
   # if @shop.save (This is not required)
  if @shop 
    flash[:success] = 'Thanks for adding new shop.'
    redirect_to @shop
  else
    flash[:error] = 'Error adding review,  please try again.'
    redirect_to @shop
  end
end

Upvotes: 2

ichigolas
ichigolas

Reputation: 7725

The first way doesn't do what you expect:

def create
  @shop = Shop.new(params[:shop]) # This won't create a new record on Shops table unless...
  @show.save                      # ...you do this
end

def create
  @shop = Shop.create(params[:shop]) # This will create a new record if everything is fine
  if @shop.save # This is redundant
    # ...
  end
end

Calling create and then save is redundant. The create method will try to make a new record and fail silently if validations are not successful. In the other hand, save will try to make a new record, but returns nil if vaildations fail, so you can use it in a if/else block.

Upvotes: 2

James Chevalier
James Chevalier

Reputation: 10874

This def new action is just for the New view (the new action in your Shop controller would correspond to the app/views/shop/new.html.erb file) - it doesn't do any creation:

def new
  @shop = Shop.new
end

There is no mention of params[:shop] in that action, because the parameters don't exist yet - that's what you're gathering in the New view.

Your def create action is the action that actually creates the database entry:

def create
  @shop = Shop.new(params[:shop])
  if @shop.save
    flash[:success] = 'Thanks for adding new shop.'
    redirect_to @shop
  else
    flash[:error] = 'Error adding review,  please try again.'
    redirect_to @shop
  end
end

You're using .new instead of .create so that you can do validations. Also, the Shop.new call doesn't actually create the record - it's @shop.save that does that.

Upvotes: 3

Related Questions