Cześć (tutaj ogromny nowicjusz Railsów), mam następujące modele:
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 utworzyć nowy sklep, 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 odmian, czytając przewodniki i samouczki tu i tam, ale jestem bardziej zdezorientowany niż wcześniej i nie mogę go uruchomić. Każda pomoc byłaby bardzo mile widziana.
ruby-on-rails
Neko
źródło
źródło
@user.build_shop(params)
Odpowiedzi:
Po pierwsze, oto jak robić, co chcesz:
Oto dlaczego twoja wersja nie działa:
Prawdopodobnie myślał, że ta praca może dlatego, jeśli użytkownik miał
has_many
stosunek do sklepu,@user.shops.create(params[:shop])
by pracować. Istnieje jednak duża różnica międzyhas_many
relacjami ihas_one
relacjami:Z
has_many
relacjąshops
zwraca obiekt kolekcji ActiveRecord, który zawiera metody, których możesz użyć do dodawania i usuwania sklepów do / od użytkownika. Jedną z tych metod jestcreate
utworzenie nowego sklepu i dodanie go do użytkownika.Z
has_one
relacją nie odzyskujesz takiego obiektu kolekcji, ale po prostu obiekt Shop, który należy do użytkownika - lub zero, jeśli użytkownik nie ma jeszcze sklepu. Ponieważ ani obiekty Shop, ani nil nie mającreate
metody, nie możesz tego użyćcreate
zhas_one
relacjami.źródło
@user.create_shop(params[:shop])
. Zobacz metody dodane przez has_one .Bardziej zwięzłym sposobem na to jest:
Zobacz metody dodane przez has_one w przewodnikach po Ruby on Rails.
źródło
@user.create_shop(params[:shop_one_info])
, utworzy shop_one, ALE jeśli uruchomisz@user.create_shop(params[:shop_two_info])
, usunie pierwszy sklep i utworzy drugi.@user.build_shop(params)
Jeszcze dwa sposoby, jeśli chcesz
save
zamiastcreate
:źródło
Wystarczy dodać do powyższych odpowiedzi -
Powyższa składnia tworzy nowy rekord, ale następnie usuwa podobny istniejący rekord.
Alternatywnie, jeśli nie chcesz wywoływać funkcji usuwania wywołania zwrotnego
Ten wątek może być pomocny. Kliknij tutaj
źródło