rails の備忘録

attr_accessible の挙動を忘れないように記録。

class LineItem < ActiveRecord::Base
  attr_accessible :product, :product_id, :id, :updated_at, :cart_id, :created_at

  belongs_to :cart
  belongs_to :product
end

上記のモデルを作成していたとすると、attr_accessible によって指定した DB のカラムに対して読み書きが出来る権限を LineItem クラスに付ける事ができる。指定していない場合 ActiveModel::MassAssignmentSecurity::Error というセキュリティエラーを吐く。これは 3.2.3 以降の仕様みたいです。

また、belongs_to は 参照元のテーブルから参照先のテーブルにアクセスする為の関連づけを行う見たいですね。この場合は carts テーブルと products テーブルへ関連づける為のモノです。この時 LineItem は Cart クラスと Product クラスに属する事になります。属する対象のクラスのインスタンスの一つに属するのでこの時の指定は単数形で書きます。

逆に Product クラスは下記のような has_many によって関連付けを行うようです。has_many は自身のモデルから対象のモデルへ 1 対多で関連を持つので対象のクラスは複数形で記述するようです。割とこの辺みそっぽい。ちなみに相互参照時にはどの様なモデルの設計かを意識する必要がある見たいですねー。Product (サービス) から見ると LineItem (商品項目) は複数内包しているものなので Product モデルに書く、と。という事は、同様に Cart モデルにも has_many :line_items してあげる必要があるって事ですよね。結構納得しました。

has_many は所有者 (モデルのインスタンスの一つ) が所有物 (モデル) を宣言してるっていうイメージだと理解しやすかったですね。
逆に belongs_to は物 (モデル) が自分の主人 (モデルのインスタンスの一つ) を宣言するってことで、関係性の整合性が取れるってことですね。

class Product < ActiveRecord::Base
  has_many :line_items
  before_destroy :ensure_not_referenced_by_any_line_item

  private
  def ensure_not_referenced_by_any_line_item
    if line_items.empty?
      return true
    else
      errors.add(:base, '品目が存在します')
      return false
    end
  end
end
class Cart < ActiveRecord::Base
  # attr_accessible :title, :body
  has_many :line_items, dependent: :destroy
end

before_destroy はその名前の如く、モデル (この場合は Product) が destroy (モデルのレコードを削除する) を実行する前に実行されるメソッドのシンボルを書いておくようです。まぁ名前のまんまなので特に疑問に思わなかったんですが、一応忘れたときの為に書いておきます。