Techioz Blog

Rails 6 has_one リレーションエラー「不明な属性を書き込めません」

概要

私はrails 6.1を使用しており、has_oneリレーションを定義しようとしています。これが私の現在のモデル定義です。

class Session < ApplicationRecord

  self.implicit_order_column = 'created_at'

  belongs_to :consultant
  belongs_to :professional
  has_one :session_summary, dependent: :destroy, foreign_key: 'session_summary_id'

end

class SessionSummary < ApplicationRecord

  validates :objectives, presence: true

  belongs_to :session, foreign_key: 'session_summary_id'
end

そしてこれらは私の移行です:

class CreateSessionSummaries < ActiveRecord::Migration[6.1]
  def change
    create_table :session_summaries do |t|
      t.string :objectives, null: false
      t.timestamps
    end
  end
end
class CreateSessions < ActiveRecord::Migration[6.1]
  def change
    create_table :sessions, id: :uuid do |t|
      t.timestamps
    end

    add_reference :sessions, :professional, type: :uuid, null: false, foreign_key: true
    add_reference :sessions, :consultant, type: :uuid, null: false, foreign_key: true
    add_reference :sessions, :session_summary, type: :bigint, null: false, foreign_key: true, index: { unique: true }
  end
end

しかし、次のようなコードを実行すると:

s= Session.new
ss = SessionSummary.new

s.session_summary = s

このエラーが発生しました:

/Users/user/.rbenv/versions/3.1.4/lib/ruby/gems/3.1.0/gems/activemodel-6.1.7.6/lib/active_model/attribute.rb:207:in `with_value_from_database': can't write unknown attribute `session_summary_id` (ActiveModel::MissingAttributeError)

          raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{name}`"
          ^^^^^

私の定義の何が間違っているのでしょうか?

解決策

add_reference :sessions、:session_summary は以下と矛盾しています。

class Session  
  has_one :session_summary

HasOne 関係の場合、session_id は session_summaries テーブルに保存されますが、移行により session_summary_id がセッション テーブルに追加されます。 add_reference ドキュメント

セッションに SummarySession を 1 つだけ持たせたい場合は、移行元を変更するだけで済みます。

add_reference :sessions, :session_summary, type: :bigint, null: false, foreign_key: true, index: { unique: true }

To (タイプの変更にも注意してください)

add_reference :session_summaries, :session, type: :uuid, null: false, foreign_key: true, index: { unique: true }

関係は自然であるため、クラス内の外部キーは必要ありません