2010-10-01 6 views
61

Salut (Rails énormes débutant ici), je les modèles suivants:Rails: créer sur l'association has_one

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

et

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

Quand je suis sur le point de créer une nouvelle boutique, je l'erreur suivante:

private method `create' called for nil:NilClass 

Ceci est mon contrôleur:

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

J'ai essayé différentes variantes en lisant des guides et des tutoriels ici et là, mais je suis plus confus qu'auparavant et je n'arrive pas à le faire fonctionner. Toute aide serait grandement appréciée.

+0

titre de la question Modifié à réfléchir question. Dupliquer de [Utiliser la construction avec une association has_one dans les rails] (http://stackoverflow.com/questions/2472982/using-build-with-a-has-one-association-in-rails) –

+1

Vous pouvez également utiliser '@ user.build_shop (params) ' – ImranNaqvi

Répondre

82

Tout d'abord, voici comment faire ce que vous voulez:

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

Maintenant, voici pourquoi votre version ne fonctionne pas:

Vous avez probablement pensé que cela pourrait fonctionner parce que si l'utilisateur avait un has_many relation à Shop, @user.shops.create(params[:shop])serait travail. Cependant, il y a une grande différence entre has_many relations et has_one relations:

Avec une relation has_many, shops retourne un objet de collection ActiveRecord, qui a des méthodes que vous pouvez utiliser pour ajouter et supprimer des magasins à/d'un utilisateur. L'une de ces méthodes est create, ce qui crée une nouvelle boutique et l'ajoute à l'utilisateur.

Avec une relation has_one, vous ne récupérez pas un tel objet de collection, mais simplement l'objet Shop qui appartient à l'utilisateur - ou nul si l'utilisateur n'a pas encore de boutique. Puisque ni les objets Boutique ni aucune méthode create, vous ne pouvez pas utiliser create de cette façon avec has_one relations.

+0

Merci pour votre réponse, sepp2k. Je vois maintenant pourquoi mon code ne pourrait pas fonctionner. – Neko

+78

Vous pouvez également utiliser '@ user.create_shop (params [: shop])'. Voir [méthodes ajoutées par has_one] (http://guides.rubyonrails.org/association_basics.html#methods-added-by-has_one). – nates

+0

La réponse choisie fonctionne, mais la solution @nates fonctionne également. +1 à vous deux. – nfriend21

147

Une façon plus concise pour ce faire est avec:

@user.create_shop(params[:shop]) 

Voir methods added by has_one en Ruby on Rails guides.

+3

C'est certainement plus meilleure approche – Magnum

+2

Méfiez-vous que si vous create_shop plus d'une fois qu'il va supprimer le magasin précédent. Par exemple, si vous lancez @ user.create_shop (params [: shop_one_info]), il créera shop_one, MAIS si vous lancez @ user.create_shop (params [: shop_two_info]), il supprimera le premier magasin et créera le deuxième. – ecoding5

+0

Le commentaire ci-dessus sur la suppression de la boutique précédente est pour Rails 3.2.18, ne sais pas sur les versions plus récentes. Impossible de modifier le commentaire après 5 min -_- – ecoding5

2

Deux façons si vous voulez save au lieu de create:

shop = @user.build_shop 
shop.save 

shop = Show.new 
shop.user = @user 
shop.save 
Questions connexes