Rails: create on has_one 关联

嗨(Rails 的大新手) ,我有以下模型:

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

还有

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

当我准备创建一个新的商店时,我得到以下错误:

private method `create' called for nil:NilClass

这是我的控制器:

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

我已经通过阅读各种指南和教程尝试了不同的变体,但是我比以前更加困惑,无法让它工作。如果你能帮忙,我将不胜感激。

64631 次浏览

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.

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.

Two more ways if you want save instead of create:

shop = @user.build_shop
shop.save


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

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