acts_asを使ってみよう

18
acts asを 使ってみよう 藤岡岳之 (xibbar)

Upload: xibbar

Post on 28-Jan-2015

119 views

Category:

Documents


1 download

DESCRIPTION

Rails勉強会@東北の資料です

TRANSCRIPT

Page 1: acts_asを使ってみよう

acts asを使ってみよう

藤岡岳之 (xibbar)

Page 2: acts_asを使ってみよう

アジェンダ

• acts as list

• acts as tree

• acts as nested set

• better nested set

Page 3: acts_asを使ってみよう

acts as listとは

• Railsに標準でついている

• 順列を扱うときに便利

Page 4: acts_asを使ってみよう

どうやって使う?• positionというinteger型のカラムを追加• modelにacts_as_listを追加

class CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.column :name, :string t.column :position, :integer end end

def self.down drop_table :users endend

class User < ActiveRecord::Base acts_as_list validates_presence_of :nameend

Page 5: acts_asを使ってみよう

使えるメソッド

• decrement_position(ポジションを1減らす)• first?(最初かどうか)• higher_item(次のアイテムを返す)• in_list?(リストに入っているかどうか)• increment_position(ポジションを1増やす)• insert_at(ポジション指定して挿入)• last?(最後かどうか)• lower_item(前のアイテムを返す)• move_higher(次のポジションへ移動)• move_lower(前のポジションへ移動)• move_to_bottom(最後のポジションへ移動)• move_to_top(最初のポジションへ移動)• remove_from_list (リストから削除)

Page 6: acts_asを使ってみよう

position範囲を限定できる

• acts_as_listに:scope=>XXXを入れる

class CreateMobileSuits < ActiveRecord::Migration def self.up create_table :mobile_suits do |t| t.column :group_id,:integer t.column :position,:integer t.column :name, :string end end

def self.down drop_table :mobile_suits endend

class MobileSuit < ActiveRecord::Base belongs_to :group acts_as_list :scope => :groupend

Page 7: acts_asを使ってみよう

矛盾に注意

• XXcrement_position

• どういう時につかうのか???

• remove_from_list

• メソッドを実行した後にpositionにnilを入れないと矛盾する

Page 8: acts_asを使ってみよう

acts as treeとは?

• Railsに標準でついている

• モデルでツリー表現を支援

Page 9: acts_asを使ってみよう

どうやって使う?• parent_idというinteger型のカラムを追加• modelにacts_as_treeを追加

class CreateDepartments < ActiveRecord::Migration def self.up create_table :departments do |t| t.column :name, :string t.column :parent_id, :integer end end

def self.down drop_table :departments endend

class Department < ActiveRecord::Base acts_as_tree :order => :idend

Page 10: acts_asを使ってみよう

使えるメソッド• ancestors(一番上の親までの一覧を配列で返す)• root(一番上の親)• self_and_siblings(siblings+自分)• siblings(自分と同じ場所にある要素一覧)

実はbelongs_toでparent、has_manyでchildrenを定義している。この他にhas_manyとbelongs_toで定義したものを使える

department=Department.find(5)department.children.create(:name=>”開発部”)

department.root.name #福島支社

Page 11: acts_asを使ってみよう

acts as tree 寸感

• 仕組みがとてもシンプルでわかりやすい

• 自分の親を把握するのが楽

• 自分の直接の子は把握できるが、子の子以降を把握するのは面倒

• 例えば、自分の子が一発で配列で欲しいよね。現状では再帰で頑張るはめに。

Page 12: acts_asを使ってみよう

acts as nested setとは?

• Railsに標準でついている• モデルでツリー表現を支援• データの表現の仕方がacts as treeと異なる

Page 13: acts_asを使ってみよう

acts as nested setの表現 root |_ Child 1 |_ Child 1.1 |_ Child 1.2 |_ Child 2 |_ Child 2.1 |_ Child 2.2

このようなツリーがあった時、 ___________________________________________________________________ ¦ Root ¦ ¦ ____________________________ ____________________________ ¦ ¦ ¦ Child 1 ¦ ¦ Child 2 ¦ ¦ ¦ ¦ __________ _________ ¦ ¦ __________ _________ ¦ ¦ ¦ ¦ ¦ C 1.1 ¦ ¦ C 1.2 ¦ ¦ ¦ ¦ C 2.1 ¦ ¦ C 2.2 ¦ ¦ ¦ 1 2 3_________4 5________6 7 8 9_________10 11_______12 13 14 ¦ ¦___________________________¦ ¦___________________________¦ ¦ ¦___________________________________________________________________¦

ID ¦ PARENT ¦ LEFT ¦ RIGHT ¦ DATA 1 ¦ 0 ¦ 1 ¦ 14 ¦ root 2 ¦ 1 ¦ 2 ¦ 7 ¦ Child 1 3 ¦ 2 ¦ 3 ¦ 4 ¦ Child 1.1 4 ¦ 2 ¦ 5 ¦ 6 ¦ Child 1.2 5 ¦ 1 ¦ 8 ¦ 13 ¦ Child 2 6 ¦ 5 ¦ 9 ¦ 10 ¦ Child 2.1 7 ¦ 5 ¦ 11 ¦ 12 ¦ Child 2.2

何がいいって、leafの検索がselect一発!!反面、おそらく構造が崩れたらピンチ

Page 14: acts_asを使ってみよう

どうやって使う?• parent_id,lft,rgtというinteger型のカラムを追加• modelにacts_as_nested_setを追加

class CreateOrganizations < ActiveRecord::Migration def self.up create_table :organizations do |t| t.column :name, :string t.column :parent_id, :integer t.column :lft, :integer t.column :rgt, :integer end end

def self.down drop_table :organizations endend

class Organization < ActiveRecord::Base acts_as_nested_setend

Page 15: acts_asを使ってみよう

使えるメソッド• add_child(child)(子を追加)

• all_children(子すべて)

• before_destroy(ネストを外して削除できる状態にする)

• child?(子どもかどうか)

• children_count(子の数)

• direct_children(直接の子)

• full_set(子全部と自分自身)

• root?(一番上の親かどうか)

• unknown?(自分自身が意味不明かどうか)

Page 16: acts_asを使ってみよう

acts as nested set 寸感

• 別の枝にぶら下げるのはどうすんのよ。

• before_destroyしてadd_child(めんどくさ)

• 深さを調べるにはどうすんのよ。

• やっぱり微妙にメソッドが足りない

そこで。。。

Page 17: acts_asを使ってみよう

better nested set• http://d.hatena.ne.jp/xibbar/20060922#1159014466

• move_to_child_of 別の場所にぶら下げる• move_to_right_of別の場所にぶら下げる• move_to_left_of別の場所にぶら下げる• root 一番元の親• roots 一番トップの親を配列で返す• level 枝の深さ• ancestors 一番元の親から直接の親までの配列• self_and_ancestors 上+自分• siblings 自分と同じレベルの要素の配列• self_and_siblings 上+自分• children_count 子の数• children 直接の子の配列• all_children 子すべての配列(孫などを含む)• left_col_name 左の名前• right_col_name 右の名前• parent_col_name 親の名前

Page 18: acts_asを使ってみよう

おしまい

• まじめに作ってみました。

• おしまい。