AWDwR "Chapter15 More Active Record"

もっとActive Record! もっとアップルのiMac G5欲しい!

Act as

DBのデータをリスト構造やツリー構造のように扱うこともできるよ。ステキじゃなーい!

まずリスト構造の場合はテーブルにpositionというカラムを定義してモデルを以下のように定義。

class Parent < ActiveRecord::Base
  has_many :children, :order => position
end

class Child < ActiveRecord::Base
  belongs_to :parent
  acts_as_list :scope => :parent_id
end

そうするとchildrenは以下のようにして扱える。

parent.children[0].name
parent.children[0].first? # 先頭?
parent.children[2].last? # 最後?
parent.children[1].lower_item # 一つ後
parent.children[1].higher_item # 一つ前
parent.children[0].move_lower # 一つ前に移動させる
parent.children[2].move_higher # 一つ後に移動させる
parent.children[0].move_to_bottom # 最後に移動させる
parent.children[2].move_to_top # 先頭に移動させる

ただし操作した後はreloadしとかないとparentはわかってくんないから注意。


次はツリー構造。この場合はテーブルにparent_idというカラムを定義してモデルを以下のように定義。

class Category < ActiveRecord::Base
  acts_as_tree
end

そうすると以下のようにして扱える。

sub = root.children.create
sub_sub = sub.children.create
sub_sub_sub = sub_sub.children.create

root.children.first.name
root.children.size
root.children.find(:all, ;conditions => "name='Book'")
sub.parent.name

Aggregation

複数のクラスからなるモデルのデータを一つのテーブルに格納するのがアグリゲーション。Customerクラスのname属性にNameクラスをマッピングしている場合は

class Customer < ActiveRecord::Base
  composed_of :name,
              :class_name => Name,
              :mapping => [[:first_name, :first],
                           [:last_name, :last]]
end

と定義。Nameクラスの属性にアクセスするには

customer.name.first
customer.name.last

とする。Nameクラスの属性を変更するには新しいインスタンスを作って属性にセットすること。

customer.name = Name.new(firstname, lastname)
customer.save

Single Table Inheritance

継承関係のクラスのオブジェクトを一つのテーブルに格納する単一テーブル継承ってやつね。その場合はテーブルにtypeというカラムを定義して以下のようにモデルを定義する。

class Person < ActiveRecord::Base
end

class Customer < Person
end

class Employee < Person
end

class Manager < Employee
end

クラス名はperson.classで取得可能。

Validation

バリデーションはいろいろあるよ。

validate # 保存時に確認
validate_on_create # 新規保存時のみ確認
validate_on_update # 更新時のみ確認

validates_acceptance_of # チェックボックスがチェックされていることを確認(規約の承認などに使うそうな)
validates_associated # 関連付けられたオブジェクトも確認
validates_confirmation_of # 確認用の属性と一致しているかどうかを確認(確認用の属性名は_confirmationを付ける。パスワードの登録の確認によく使われるね)
validates_each # 複数の属性をブロックを使って確認
validates_exclusion_of # 指定した値のセットに含まれていないことを確認
validates_format_of # 指定した正規表現にマッチすることを確認
validates_inclusion_of # 指定した値のセットに含まれていることを確認
validates_length_of # 文字列の長さが指定された長さであることを確認(最大値、最小値を設定可能)
validates_numericality_of # 数値であることを確認(only_integer => trueとすると整数であることを確認)
validates_presence_of # 空でないことを確認
validates_uniqueness_of # ユニークであることを確認


続きはまた。