2013年2月14日木曜日

railsでDBのトリガーっぽいことをやる

やりたい事は以下の
『モデルAを作成(DBにレコードを登録)した際に、別のモデルも登録する』
みたいなの。

抽象的に書くと分からんので具体例にすると『全種類合わせた商品購入履歴を登録する』みたいなやつ。
例としては、ぶき・ぼうぐ・どうぐの購入履歴テーブルがあった時に、全部の購入履歴をと管理するようなテーブルを同時に用意しておくみたいなやつ。

こんなもん『SQL結合すれば専用テーブル作らんでもいいだろ』というはなしもあるのですが、以下のメリットがあるので作ることにしました。

  • 複雑なSQLを書かなくてて済む
  • 履歴⇒履歴詳細データという辿り方が簡単にできる(前購入履歴には各履歴への参照キーを持たせる想定)


よくある話なのでWeb上にもそこら中に情報が載ってますが、備忘録として書いておきます。
#railsはモデルの関連性が簡単にかけるのでこの手の話はすぐできる。
#あと、そもそももっと上手くやる方法があるのかもしれん風来のシレン。

整理すると

  • やりたいこと:あるレコード新規登録時に別のテーブルにもレコードを登録するようにする
  • 実現の基本方針:(きっと)railsのActiveRecordにはいい感じのメソッドがあるのでそれでやる


で、以下のようにした。
# 武器購入履歴モデル
class BukiKounyuRireki < ActiveRecord::Base
  # 以下の情報を持つ
  # 購入した武器のID
  # 購入者の名前
  # 個数
  attr_accessible :buki_id, :user_id, :count

  # レコード登録時に発動するコールバックafter_createメソッドを定義
  # |record| は登録した元レコードの中身が入っている
  after_create {|record|
    # 前購入履歴テーブルにレコード(購入者、武器購入履歴ID[武器IDではない],購入物タイプ)を登録する
    AllRireki.create user_id: record.userid, rireki_primary_id: record.id, item_type: 1
  }
end

サマリーすると、

  • after_createメソッドを使って定義します
  • フック元のレコードはafter_create のブロック内で宣言した第一引数として使用できます(正確な説明ではない可能性が高い…)

ということです。

↑のモデル関連だとあんまり力を発揮しませんが、履歴の幅を広げて、
どんな道具を使ったか記録したい
誰と話したか記録したい
とか言うように、元履歴のテーブルの構造がバラバラになれば今回のようなモデル(全履歴管理モデル)がパワーを発揮してくる(とおもう)。

0 件のコメント:

コメントを投稿