web-dev-qa-db-ja.com

railsのhas_one関連付けでビルドを使用する

この例では、userなしでprofileを作成し、後でそのユーザー用にprofileを作成します。 has_oneアソシエーションでビルドを使用しようとしましたが、爆発しました。私がこれが機能していると思う唯一の方法は、has_manyを使用することです。 userは、最大で1つのprofileのみを持つことになっています。

私はこれを試してきました。私は持っています:

class User < ActiveRecord::Base
  has_one :profile
end

class Profile < ActiveRecord::Base
  belongs_to :user
end

しかし、私がするとき:

user.build_profile 

エラーが表示されます:

ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'profiles.user_id' in 'where clause': SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4)  LIMIT 1

Railsに0個または1個の関連付けを持つ方法はありますか?

134
espinet

buildメソッドのシグネチャは、has_onehas_manyの関連付けによって異なります。

class User < ActiveRecord::Base
  has_one :profile
  has_many :messages
end

has_many関連付けのビルド構文:

user.messages.build

has_one関連付けのビルド構文:

user.build_profile  # this will work

user.profile.build  # this will throw error

詳細については、has_oneアソシエーション ドキュメント をお読みください。

349
Harish Shetty

エラーメッセージをよく見てください。 profileテーブルに必要な列user_idがないことを示しています。モデルに関係を設定することは、答えの一部にすぎません。

また、user_id列をプロファイルテーブルに追加する移行を作成する必要があります。 Railsはこれが存在することを期待し、そうでない場合はプロファイルにアクセスできません。

詳細については、次のリンクをご覧ください。

関連付けの基本

18
sosborn

ユースケースによっては、メソッドをラップし、見つからない場合に関連付けを自動的に構築すると便利です。

old_profile = instance_method(:profile)
define_method(:profile) do
  old_profile.bind(self).call || build_profile
end

#profileメソッドを呼び出すと、関連するプロファイルが返されるか、新しいインスタンスが作成されます。

ソース: サルがメソッドにパッチを適用するとき、新しい実装からオーバーライドされたメソッドを呼び出すことができますか?

0
Shiyason