2010-10-01 14 views
61

Hi (ogromne Szyny newbie tutaj), mam następujące modele:Szyny: tworzenie na stowarzyszenie has_one

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

i

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

Kiedy mam zamiar stworzyć nowy sklep, ja Pojawia się następujący błąd:

private method `create' called for nil:NilClass 

to jest mój kontroler:

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

Próbowałem różnych wersji, czytając przewodniki i samouczki tu i tam, ale jestem bardziej zdezorientowany niż wcześniej i nie mogę go uruchomić. Każda pomoc będzie bardzo ceniona.

+0

Edited tytuł pytanie odzwierciedlać pytanie. Duplikat [Używanie kompilacji ze skojarzeniem has_one w szynach] (http://stackoverflow.com/questions/2472982/using-build-with-a-has-one-association-in-rails) –

+1

możesz również użyć '@ user.build_shop (params) ' – ImranNaqvi

Odpowiedz

82

Przede wszystkim, oto jak to zrobić, co chcesz:

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

Teraz oto dlaczego twoja wersja nie działa:

pewnie myślał, że to może działać, ponieważ, jeśli użytkownik miał has_many w stosunku do Shop, @user.shops.create(params[:shop])będzie pracować. Jednak istnieje duża różnica pomiędzy has_many stosunków i has_one Relacje:

z has_many relacji, shops zwraca obiekt kolekcji ActiveRecord, który ma metod, które można wykorzystać do dodawania i usuwania sklepy z/do użytkownika. Jedną z tych metod jest create, która tworzy nowy sklep i dodaje go użytkownikowi.

Stosując relację has_one, nie można odzyskać takiego obiektu kolekcji, ale po prostu obiektu Shop należącego do użytkownika - lub zerowego, jeśli użytkownik nie ma jeszcze sklepu. Ponieważ ani obiekty Shop ani zero nie mają metody create, nie można w ten sposób używać create z relacjami has_one.

+0

Dzięki za odpowiedź, sepp2k. Teraz widzę, dlaczego mój kod nie mógł działać. – Neko

+78

Można również użyć '@ user.create_shop (params [: shop])'. Zobacz [metody dodane przez has_one] (http://guides.rubyonrails.org/association_basics.html#methods-added-by-has_one). – nates

+0

Wybrana odpowiedź działa, ale rozwiązanie @nates działa również. +1 do was obojga. – nfriend21

147

bardziej zwięzły sposób, aby to zrobić, to z:

@user.create_shop(params[:shop]) 

Zobacz methods added by has_one w Ruby on Rails Guides.

+3

To zdecydowanie lepsze podejście – Magnum

+2

Pamiętaj, że jeśli create_shop więcej niż raz usunie poprzedni sklep. Na przykład, jeśli uruchomisz '@ user.create_shop (params [: shop_one_info])' utworzy shop_one, ALE jeśli uruchomisz '@ user.create_shop (params [: shop_two_info])' to usunie pierwszy sklep i utworzy Drugi. – ecoding5

+0

Powyższa uwaga dotycząca usuwania poprzedniego sklepu dotyczy Railsów 3.2.18, nie wiem o nowszych wersjach. Nie można edytować komentarza po 5 min. -_- – ecoding5

2

Jeszcze dwa sposoby jeśli chcesz save zamiast create:

shop = @user.build_shop 
shop.save 

shop = Show.new 
shop.user = @user 
shop.save 
Powiązane problemy