Rails: create on has_one association
Ruby on-RailsRuby 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