Rails: создайте на ассоциации has_one - PullRequest
87 голосов
/ 01 октября 2010

Привет (огромный новичок в 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])

Я пробовал разные варианты, читая руководства и учебники здесь и там, но я более запутан, чем раньше, ине могу заставить его работать.Любая помощь будет принята с благодарностью.

Ответы [ 4 ]

191 голосов
/ 08 ноября 2013

Более краткий способ сделать это с помощью:

@user.create_shop(params[:shop])

См. методы, добавленные has_one в руководствах по Ruby on Rails.

104 голосов
/ 01 октября 2010

Прежде всего, вот как делать то, что вы хотите:

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

Теперь вот почему ваша версия не работает:

Возможно, вы подумали, что это может сработать, потому что если у пользователя есть отношение has_many к магазину, @user.shops.create(params[:shop]) будет работать . Однако между has_many отношениями и has_one отношениями существует большая разница:

При наличии отношения has_many shops возвращает объект коллекции ActiveRecord, в котором есть методы, которые можно использовать для добавления и удаления магазинов для пользователя. Одним из таких методов является create, который создает новый магазин и добавляет его пользователю.

С отношением has_one вы не получаете такой объект коллекции, а просто объект Shop, принадлежащий пользователю - или ноль, если у пользователя еще нет магазина. Поскольку ни у объектов Shop, ни у nil нет метода create, вы не можете использовать create таким образом с отношениями has_one.

7 голосов
/ 13 марта 2017

Еще два способа, если вы хотите save вместо create:

shop = @user.build_shop
shop.save

shop = Show.new
shop.user = @user
shop.save
0 голосов
/ 08 мая 2019

Просто чтобы добавить к ответам выше -

@user.create_shop(params[:shop])

Выше синтаксиса создает новую запись, но впоследствии удаляет аналогичную существующую запись.

В качестве альтернативы, если вы не хотите инициировать удаление обратного вызова

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

Эта тема может быть полезна. Нажмите здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...