Rails: создать связь 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])
Я пробовал разные варианты, читая руководства и учебники здесь и там, но я более смущен, чем раньше, и не могу заставить его работать. Любая помощь будет принята с благодарностью.
Ответы
Ответ 1
Прежде всего, вот как сделать то, что вы хотите:
@user = current_user
@shop = Shop.create(params[:shop])
@user.shop = @shop
Теперь, почему ваша версия не работает:
Вероятно, вы считали, что это может сработать, потому что если бы у Пользователя было отношение has_many
к Shop, @user.shops.create(params[:shop])
работало бы. Однако существует большая разница между отношениями has_many
и has_one
:
С отношением has_many
shops
возвращает объект коллекции ActiveRecord, в котором есть методы, которые вы можете использовать для добавления и удаления магазинов/от пользователя. Один из этих методов - create
, который создает новый магазин и добавляет его пользователю.
С отношением has_one
вы не возвращаете такой объект коллекции, а просто объект Shop, принадлежащий пользователю, или nil, если пользователь еще не имеет магазина. Поскольку ни объекты Shop, ни nil не имеют метода create
, вы не можете использовать create
таким образом с отношениями has_one
.
Ответ 2
Более краткий способ сделать это:
@user.create_shop(params[:shop])
См. методы, добавленные has_one в руководствах Ruby on Rails.
Ответ 3
Еще два способа, если вы хотите save
вместо create
:
shop = @user.build_shop
shop.save
shop = Show.new
shop.user = @user
shop.save
Ответ 4
Просто чтобы добавить к ответам выше -
@user.create_shop(params[:shop])
Выше синтаксис создает новую запись, но впоследствии удаляет аналогичную существующую запись.
В качестве альтернативы, если вы не хотите инициировать удаление обратного вызова
Shop.create(user_id: user.id, title: 'Some unique title')
Эта тема может быть полезной. кликните сюда