2010-10-01 3 views
61

Hi (огромное Rails новичка здесь), у меня есть следующие модели:Rails: создать на HAS_ONE ассоциации

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]) 

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

+0

Edited вопрос название, чтобы отразить вопрос. Дубликат [Использование сборки с ассоциацией has_one в рельсах] (http://stackoverflow.com/questions/2472982/using-build-with-a-has-one-association-in-rails) –

+1

вы также можете использовать '@ user.build_shop (params) ' – ImranNaqvi

ответ

82

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

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

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

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

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

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

+0

Спасибо за ваш ответ, sepp2k. Теперь я вижу, почему мой код не смог работать. – Neko

+78

Вы также можете использовать '@ user.create_shop (params [: shop])'. См. [Методы, добавленные has_one] (http://guides.rubyonrails.org/association_basics.html#methods-added-by-has_one). – nates

+0

Ответ на выбранные работы, но также работает решение @nates. +1 для вас обоих. – nfriend21

147

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

@user.create_shop(params[:shop]) 

Смотрите methods added by has_one в Ruby On Rails гидами. больше

+3

Это определенно более подходящий подход – Magnum

+2

Опасайтесь, что если вы создадите_shop более одного раза, он удалит предыдущий магазин. Например, если вы запустите '@ user.create_shop (params [: shop_one_info]), он создаст shop_one, НО если вы запустите' @ user.create_shop (params [: shop_two_info]), что он удалит первый магазин и создаст второй. – ecoding5

+0

Вышеупомянутый комментарий об удалении предыдущего магазина относится к Rails 3.2.18, не знаю о более поздних версиях. Невозможно отредактировать комментарий после 5 минут -_- – ecoding5

2

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

shop = @user.build_shop 
shop.save 

shop = Show.new 
shop.user = @user 
shop.save 
Смежные вопросы