狠狠撸

狠狠撸Share a Scribd company logo
イケテル
better nested set
      研究会
   藤岡岳之(xibbar)
アジェンダ




better nested setを使って組織図を書く
手軽に書きたいんだ~!
Sectionモデルを作成1




better nested setをインストール
Sectionモデルを作成2
migrationファイル
  モデルはSectionという名前にすることにして、使用
  するカラムはnameだけに
  better nested setにはparent_id、lft、rgtとい
  う:integerなカラムが必要
class CreateSections < ActiveRecord::Migration
 def self.up
   create_table :sections do ?t?
    t.column :name, :string, :null=>false
    t.column :parent_id, :integer
    t.column :lft,    :integer
    t.column :rgt,      :integer
   end
 end
 def self.down
   drop_table :sections
 end
end
Sectionモデルを作成3

app/models/section.rbの中身


   class Section < ActiveRecord::Base
           acts_as_nested_set
   end
データを作成

              ツリーを作成してみる
%   ./script/runner   'Section.create(:name=>"日本Ruby会議")'
%   ./script/runner   'Section.create(:name=>"東京Ruby会議").move_to_child_of Section.?nd_by_name("日本Ruby会議")'
%   ./script/runner   'Section.create(:name=>"札幌Ruby会議").move_to_child_of Section.?nd_by_name("日本Ruby会議")'
%   ./script/runner   'Section.create(:name=>"Akasaka.rb").move_to_child_of Section.?nd_by_name("東京Ruby会議")'
%   ./script/runner   'Section.create(:name=>"Asakusa.rb").move_to_child_of Section.?nd_by_name("東京Ruby会議")'




              DBの中身は
                             # select * from sections;
                              id ?   name       ? parent_id ? lft ? rgt
                             ----+--------------+-----------+-----+-----
                               1 ? 日本Ruby会議 ?                ? 1 ? 10
                               2 ? 東京Ruby会議 ?              1? 2? 7
                               3 ? 札幌Ruby会議 ?              1? 8? 9
                               4 ? Akasaka.rb ?            2? 3? 4
                               5 ? Asakusa.rb ?            2? 5? 6
                             (5 rows)
自作プラグインを導入



./script/plugin install http://xibbar.net/svn/
rails/plugins/trunk/acts_as_section_map/
モデルに一行追加


     class Section < ActiveRecord::Base
      acts_as_nested_set
      acts_as_section_map
     end


※?acts_as_section_mapは
??acts_as_nested_setの下に書くこと
コントローラー
                1行追加

class WelcomeController <ApplicationController
 def index
  @table2=Section.table2
 end
end
ビュー
index.rhtml
 <% section_map(@table2) do ?table? %>
  <%=table.name%>
 <% end %>
   ※?テーブルの中身はブロックで指定




    ※?プラグインの魔法で、
    たったこれだけで組織図完成
関连テーブル
    user.rb                                       section.rb
                                              class Section < ActiveRecord::Base
class CreateUsers < ActiveRecord::Migration
                                               acts_as_nested_set
 def self.up
                                               acts_as_section_map
   create_table :users do ?t?
                                               has_many :users
    t.column :name, :string, :null=>false
                                              end
    t.column :section_id, :integer
   end
 end
 def self.down
   drop_table :users
 end
end


class User < ActiveRecord::Base
 belongs_to :section
end
データ作成

        userを作成し、sectionにぶら下げる
%   ./script/runner   'Section.?nd_by_name("Akasaka.rb").users   <<   User.create(:name=>"takai")'
%   ./script/runner   'Section.?nd_by_name("Akasaka.rb").users   <<   User.create(:name=>"koichiroo")'
%   ./script/runner   'Section.?nd_by_name("Akasaka.rb").users   <<   User.create(:name=>"takedasoft")'
%   ./script/runner   'Section.?nd_by_name("Asakusa.rb").users   <<   User.create(:name=>"a_matsuda")'
%   ./script/runner   'Section.?nd_by_name("Asakusa.rb").users   <<   User.create(:name=>"kakutani")'
%   ./script/runner   'Section.?nd_by_name("Asakusa.rb").users   <<   User.create(:name=>"maiha")'
ビューも直す
index.rhtml
<% section_map(@table2) do ?table? %>
 <%=table.name%>
 <ul>
 <% table.users.each do ?user?%>
  <li><%=user.name%></li>
 <%end%>
 </ul>
<% end %>
見た目を直そう
index.rhtml
<% section_map(@table2,:table=>{:cellspacing=>"0",:style=>"border-collapse:collapse;"},
           :td=>{:valign=>"top",:style=>"border:1px solid #666666;color:navy;"}) do ?table? %>
 <%=table.name%>
 <ul>
 <% table.users.each do ?user?%>
  <li style="font-size:12px;color:green"><%=user.name%></li>
 <%end%>
 </ul>
<% end %>
のろくない?



数が多いとのろいぞ
でも、なんとかしちゃる
でも今日はおしまい
続きは次回以降
イケテルDB
  チューニング

xibbarこと藤岡岳之
ブログのぶくま
これでぎりぎり卒論になるんじゃなかろうか。
長谷川がこけたら、これにしようかな。。。



     なんだこれ!!
巨大な組織

(1..4).each{?n?Section.create(:name=>"Section:#{n}")}
(5..60).each{?n?2.times{?m?
Section.?nd_or_create_by_name("Section:#{n*2+m
+3}").move_to_child_of
Section.?nd_by_name("Section:#{n}")}}




  120組織のツリーを作るスクリプト
遅すぎる

 User Load (0.000204) SELECT * FROM users
WHERE (users.section_id = 124)
Completed in 18.13171 (0 reqs/sec) ? Rendering:
7.49291 (41%) ? DB: 10.46457 (57%) ? 200 OK
[http://localhost/welcome]


            表示に18秒っておい!
インデックスを張ってみる

 User Load (0.000182) SELECT * FROM users
WHERE (users.section_id = 124)
Completed in 10.01978 (0 reqs/sec) ? Rendering:
6.97071 (69%) ? DB: 2.87357 (28%) ? 200 OK
[http://localhost/welcome]

             10秒に短縮!
          まだ使い物にならないけど
すばやさの種を投入
class AddDepthToSections < ActiveRecord::Migration
 def self.up
   add_column :sections,:depth,:integer
   Section.set_depth
 end


 def self.down
  remove_column :sections,:depth
 end
end


  depthという項目を追加し、
  値をセットする。depthというのは
  文字通り深さの値(levelの結果)
すばやさの種の結果

 User Load (0.000180) SELECT * FROM users WHERE
(users.section_id = 124)
Completed in 0.84391 (1 reqs/sec) ? Rendering: 0.40329 (47%) ?
DB: 0.27316 (32%) ? 200 OK [http://localhost/welcome]




         1秒切ってメデタシメデタシ
ちょっとだけ解説



のろさの原因はsectionが自分自身の深さを
知るためにselect count(*)していることに
ある。(levelメソッド)
これをカラムとして持つとツリーの構築の早
さが圧倒的に違う(つまりdepthカラム)
benchmark
% ./script/performance/benchmarker 100 'Section.?nd(:all).map(&:level)'
        user   system   total   real
#1    5.790000 0.470000 6.260000 ( 10.331682)

% ./script/performance/benchmarker 100 'Section.?nd(:all).map(&:depth)'
        user   system   total   real
#1    0.610000 0.010000 0.620000 ( 0.784886)


                ちなみにindex張る前は
% ./script/performance/benchmarker 100 'Section.?nd(:all).map(&:level)'
        user   system   total   real
#1    6.180000 0.530000 6.710000 ( 20.693455)


            20.693 0.784=26.394
                  26倍早くなった!!
グー

おしまい


       http://www001.upp.so-net.ne.jp/masa_gallery/edo.html

More Related Content

More Better Nested Set