Rails:has_one関連で作成


100

こんにちは(ここでは巨大な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])

私はあちこちでガイドやチュートリアルを読んでさまざまなバリエーションを試しましたが、以前よりも混乱しており、機能させることができません。どんな助けでも大歓迎です。


質問を反映するように質問のタイトルを編集しました。重複レールにhas_oneの関連でビルドを使用して
マルク=アンドレ・Lafortune

1
使用することもできます@user.build_shop(params)
ImranNaqvi

回答:


123

まず最初に、ここにあなたが望むことをする方法があります:

@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コレクションオブジェクトを返します。これらのメソッドの1 createつはで、新しいショップを作成してユーザーに追加します。

has_oneリレーションを使用すると、このようなコレクションオブジェクトは返されませんが、ユーザーに属するShopオブジェクトが返されます。ユーザーがまだショップを持っていない場合はnilになります。Shopオブジェクトにもnilにもcreateメソッドがないため、createこの方法をhas_oneリレーションで使用することはできません。


答えてくれてありがとう、sepp2k。私のコードが機能しなかった理由がわかります。
Neko

118
も使用できます@user.create_shop(params[:shop])has_oneによって追加されたメソッドを参照してください。
2013

選択した答えは機能しますが、@ natesソリューションも機能します。両方に+1します。
nfriend21

同じことを考えていたので答えに+1、これがなぜであるかを説明するために答えに+1、最適な解決策を与えるためにコメントに+1。
deivid 2013

224

これを行うためのより簡潔な方法は次のとおりです。

@user.create_shop(params[:shop])

Ruby on Railsガイドのhas_oneによって追加されたメソッドを参照してください。


6
これは間違いなくより優れたアプローチです
マグナム

7
create_shopを複数回実行すると、前のショップが削除されることに注意してください。たとえば、実行@user.create_shop(params[:shop_one_info])するとshop_oneが作成されますが、実行すると@user.create_shop(params[:shop_two_info])最初のショップが削除され、2番目のショップが作成されます。
ecoding5 2016年

前のショップの削除に関する上記のコメントはRails 3.2.18に関するものであり、より新しいバージョンについてはわかりません。5分後にコメントを編集できない-_-
ecoding5

解決策が見つかったので、関連付けられたモデルに一意性を設定しなかったので、この例のShopモデルでの設定方法に従って設定してください。
ecoding5 2016年

使用することもできます@user.build_shop(params)
ImranNaqvi 2016年

7

必要saveに応じて、次の2つの方法がありますcreate

shop = @user.build_shop
shop.save

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

1

上記の回答に追加するだけです-

@user.create_shop(params[:shop])

上記の構文は新しいレコードを作成しますが、その後、同様の既存のレコードを削除します。

または、削除コールバックをトリガーしたくない場合

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

このスレッドは役に立つかもしれません。ここをクリック

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.