Rails: create a has_one relationship

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 am going to create a new store, 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 tried different options, reading manuals and tutorials here and there, but I'm more confused than before and can't make it work. Any help would be greatly appreciated.

+85
ruby-on-rails
01 Oct 2018-10-10
source share
4 answers

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

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

Now why is your version not working:

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

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

With a has_one relationship has_one you are not returning such a collection object, but simply a Shop object owned by the user, or nil if the user does not already have a store. Since neither Shop objects nor nil have a create method, you cannot use create this way with has_one relationships.

+103
01 Oct 2018-10-10
source share

A more concise way to do this:

 @user.create_shop(params[:shop]) 

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

+188
Nov 07 '13 at 21:55
source share

Two more ways if you want to save instead of create :

 shop = @user.build_shop shop.save shop = Show.new shop.user = @user shop.save 
+6
Mar 13 '17 at 18:08
source share

Just to add to the answers above -

 @user.create_shop(params[:shop]) 

The above syntax creates a new record, but subsequently deletes a similar existing record.

Alternatively, if you do not want to initiate deletion of the callback

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

This topic may be helpful. Click here

0
May 08 '19 at 9:16
source share



All Articles