Categories
open all | close allTags
CSRF | タグ | テスト | パソコン | フォーム | RESTful | Flash | 国際化 | スキンエンジン | Migration | デュアル・コア | 認証 | カテゴリ | Subversion | 名称 | Aptana | rubygems | JustPosted | ドキュメント | rakeSearch
そうか,クロージャって役に立つんだ
どうもいまいちクロージャの有用性が分かっていなかったのですが,階層カテゴリー部分の表示を作っていて,やっと役に立つことが分かったような気がしました。具体的に言うと,<%categorylist%>で表示する部分というのは既に作ってあったのですが,今回,アイテム投稿画面を作るときに,またカテゴリーのツリー表示が必要なことに気付いたわけです。最初はコピペして,同じようなことをやらせようとしたのですが,どうも効率が悪いし,アルゴリズムにバグがあったり,データ構造を変えたら両方直す必要があります。
そこで,Blogモデルの中に表示ルーチンを移し,そこからブロックを呼び出すような形に変えてみました。
def category_tree
tempbuffer = ""
level = 0
self.categories.inject(nil) do |last_right, cat|
# cat is under the last leaf
if !last_right || (last_right > cat.cleft)
level += 1
tempbuffer += yield(:level_up, level)
#
elsif (last_right + 2 <= cat.cleft)
tempbuffer += yield(:item_close, level)
(last_right+2..cat.cleft).each do |i|
level -= 1
tempbuffer += yield(:level_down, level)
end
else
tempbuffer += yield(:item_close, level)
end
tempbuffer += yield(:item, level, cat)
last_right = cat.cright
end
if (level > 1)
tempbuffer += yield(:level_down, level)
end
(level..1).each do |i|
tempbuffer += yield(:item_close, level)
end
tempbuffer += yield(:level_down, level)
return tempbuffer
endこれをスキン変数の実行部分では
def parse_categorylist params
blog = params[2] ? Blog.find_by_bname(params[2]) : @controller.blog
templatename = params[1]
template = Template.find_by_tdname(templatename)
bd = blog.basic_data
data = Hash.new
blog.category_tree do |type, level, cat|
data['level'] = level.to_s
case type
when :level_up
fill(template['CATLIST_HEADER'], bd.merge(data))
when :level_down
fill(template['CATLIST_FOOTER'], bd.merge(data))
when :item
data['catlink'] = url_for(:controller=>'categories', :catid=>cat.catid, :action=>'show')
fill(template['CATLIST_LISTITEM'], data.merge(cat.attrs))
when :item_close
fill(template['CATLIST_LISTITEM_END'], bd.merge(data))
end
end
endといった形でblog.category_treeにブロックを与える格好で呼び出します。かなりすっきりしたような気がします。管理画面でカテゴリーツリーが必要なときもblog.category_treeを使えばロジックは不要になります。
さらに,こういった構造に変えるメリットとして,スキン/テンプレートの実行部分とデータ構造を切り離せます。プラグインのイベント呼び出しを,これまではスキン/テンプレートの中からやる形だったのですが,モデル側に全部移せそうです。今後,スキン・エンジンを新たに作るときなどに,負担が大きく減るはずです。
Comments
No comments yet. You can be the first!