Rails: create on has_one association

Ruby on-Rails

Ruby on-Rails Problem Overview


Hi (huge Rails newbie here), I have the following models:

class Shop < ActiveRecord::Base
  belongs_to :user
  validates_uniqueness_of :title, :user_id, :message => "is already being used"
end

and

class User < ActiveRecord::Base
  has_one :shop, :dependent => :destroy
end

When I'm about to create a new shop, I get the following error:

private method `create' called for nil:NilClass

This is my controller:

@user = current_user
@shop = @user.shop.create(params[:shop])

I've tried different variations by reading guides and tutorials here and there, but I'm more confused than before and can't get it to work. Any help would be greatly appreciated.

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

A more concise way to do this is with:

@user.create_shop(params[:shop])

See methods added by has_one in the Ruby on Rails guides.

Solution 2 - Ruby on-Rails

First of all, here is how to do what you want:

@user = current_user
@shop = Shop.create(params[:shop])
@user.shop = @shop

Now here's why your version did not work:

You probably thought that this might work because if User had a has_many relation to Shop, @user.shops.create(params[:shop]) would work. However there is a big difference between has_many relations and has_one relations:

With a has_many relation, shops returns an ActiveRecord collection object, which has methods that you can use to add and remove shops to/from a user. One of those methods is create, which creates a new shop and adds it to the user.

With a has_one relation, you don't get back such a collection object, but simply the Shop object that belongs to the user - or nil if the user doesn't have a shop yet. Since neither Shop objects nor nil have a create method, you can't use create this way with has_one relations.

Solution 3 - Ruby on-Rails

Two more ways if you want save instead of create:

shop = @user.build_shop
shop.save

shop = Show.new
shop.user = @user
shop.save

Solution 4 - Ruby on-Rails

Just to add to above answers -

@user.create_shop(params[:shop])

Above syntax creates new record but it subsequently deletes similar existing record.

Alternatively, if you do not want to trigger delete callback

Shop.create(user_id: user.id, title: 'Some unique title')

This thread might be helpful. Click here

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
QuestionNekoView Question on Stackoverflow
Solution 1 - Ruby on-RailsnatesView Answer on Stackoverflow
Solution 2 - Ruby on-Railssepp2kView Answer on Stackoverflow
Solution 3 - Ruby on-RailsFellow StrangerView Answer on Stackoverflow
Solution 4 - Ruby on-RailsRaisView Answer on Stackoverflow