redmine 読み (5)
ええと、projects コントローラ確認中なのか。昨日 render_menu という手続きを見てたんですが微妙に中途半端で終わってますね。中身をざっくり見たところでは
- menu_items_for で引数から node を取り出してそれらについて
- render_menu_node という手続きの戻りを link な配列に追加
- content_tag を使って ul なリストにしている
のかどうなのか。掘削して確認。
menu_items_for 手続き
これも lib/redmine/menu_manager.rb で定義されている模様。その前にそもそも render_menu がどんな形で呼び出されているかというと以下。
render_menu((project && !project.new_record?) ? :project_menu : :application_menu, project)
手続き定義は以下です(一部のみ)。
def render_menu(menu, project=nil)
menu には :project_menu または :application_menu が格納らしい。menu_items_for の肝心な所を以下に。
def menu_items_for(menu, project=nil) items = [] Redmine::MenuManager.items(menu).root.children.each do |node| if allowed_node?(node, User.current, project)
まず、Redmine::MenuManager て何か。と思ったらこれって lib/redmine/menu_manager.rb なのかな。先頭確認したら以下になってました。
module Redmine module MenuManager
つーことは、と言いつつ M-x occur で menu_manager.rb をアレしてみたら以下な記述に hit してます。
class << self def map(menu_name) @items ||= {} mapper = Mapper.new(menu_name.to_sym, @items) if block_given? yield mapper else mapper end end def items(menu_name) @items[menu_name.to_sym] || MenuNode.new(:root, {}) end end
うう、クラス定義のあたりでスデに微妙。明快な解は得ておらぬのですが、シングルトンなナニ、って思ってて良いのかどうか。つうか Mapper って何でしょ。
と思ったら ManuManager でクラスが定義されてますね。
Redmine::MenuManager.items(menu) てのは @items 属性なんですが、items メソドにもある通りそれは MenuNode クラスのオブジェクトになっている模様。これも menu_manager.rb で定義されていますね。最終的に Redmine::MenuManager.items(menu).root.children は配列なカンジなんですが、それにしても Mapper#push が複雑すぎる。
とはいえ push メソドの中の target_root は MenuNode なオブジェクトになるのか。ちょっとここもあまり深く掘らずにスルーの方向ってことで。そもそも redmine あまり使ったことがないのにソース確認とか無茶すぎる。
projects_controller.rb
先頭部分の記述をきちんと確認入れたい。例えば menu_item
class ProjectsController < ApplicationController menu_item :overview menu_item :roadmap, :only => :roadmap menu_item :settings, :only => :settings
これも lib/redmine/menu_manager.rb にて定義されている模様。ClassMethods という module ですね。以下なコメントが参考になるのかどうか。
# Examples:
# * menu_item :tickets # => sets the menu name to :tickets for the whole controller
# * menu_item :tickets, :only => :list # => sets the menu name to :tickets for the 'list' action only
Set the menu item name for a controller ってのはどーゆー意味なのかなぁ。
む、settings なタブを開いたらサブメニューみたいのがありますね。むむむ、と言いつつ app 配下を menu_item で grep したら以下な出力。
$ find app |xargs grep menu_item app/helpers/application_helper.rb: { :value => project_path(:id => p, :jump => current_menu_item) } app/helpers/application_helper.rb: b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') app/helpers/application_helper.rb: b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') } app/controllers/reports_controller.rb: menu_item :issues app/controllers/repositories_controller.rb: menu_item :repository app/controllers/repositories_controller.rb: menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers] app/controllers/journals_controller.rb: menu_item :issues app/controllers/settings_controller.rb: menu_item :plugins, :only => :plugin app/controllers/issues_controller.rb: menu_item :new_issue, :only => [:new, :create] app/controllers/auth_sources_controller.rb: menu_item :ldap_authentication app/controllers/files_controller.rb: menu_item :files app/controllers/versions_controller.rb: menu_item :roadmap app/controllers/projects_controller.rb: menu_item :overview app/controllers/projects_controller.rb: menu_item :roadmap, :only => :roadmap app/controllers/projects_controller.rb: menu_item :settings, :only => :settings app/controllers/projects_controller.rb: redirect_to_project_menu_item(@project, params[:jump]) && return app/controllers/messages_controller.rb: menu_item :boards app/controllers/timelog_controller.rb: menu_item :issues app/controllers/calendars_controller.rb: menu_item :calendar app/controllers/activities_controller.rb: menu_item :activity app/controllers/queries_controller.rb: menu_item :issues app/controllers/wikis_controller.rb: menu_item :settings app/controllers/admin_controller.rb: menu_item :projects, :only => :projects app/controllers/admin_controller.rb: menu_item :plugins, :only => :plugins app/controllers/admin_controller.rb: menu_item :info, :only => :info app/controllers/issue_categories_controller.rb: menu_item :settings app/controllers/gantts_controller.rb: menu_item :gantt
うーん、よく分からんな。なんで wikis_controller で settings なのかとか。ちょっとここは保留ってことにして、ってきちんと確認しときたいトリガで始まってるのにこの終わりかたはちと情け無いなぁ。
もうすこし
列挙のみ。menu_item 呼び出しなコントローラは以下。
- reports
- repositories
- journals
- settings
- issues
- auth_sources
- files
- versions
- projects
- messages
- timelog
- calendars
- activities
- queries
- wikis
- issue_categories
- gantts
これら、いずれも projects 配下なソレなのかどうか。
- /projects/:id/issues/report : reports#issue_report
- /projects/:project_id/repositories : repositories#create
- /issues/changes(.:format) : journals#index
- /projects/:id/settings : projects#settings
- /projects/:project_id/issues/ : issues#index
- /auth_sources : auth_sources#index
- /projects/:project_id/files : files#index
- /projects/:project_id/versions : versions#index
- /projects : projects#index
- /boards/:boards_id/topics/:id : messages#show
- /projects/:project_id/issue/:issue_id/time_entries : timelog#index
- /projects/:project_id/issues/calendar : calendar#show
- /projects/:id/activity : activities#index
- /queries : queries#index
- /projects/:id/wiki : wikis#edit
- /projects/:project_id/issue_categories : issue_categories#index
- /projects/:project_id/issues/gantt : gantts#how
なんかそうではなさげなのも入ってるように見えますね。
もうすこし
基本的に menu_item メソドは menu_items という hash な属性に引数な id を格納してる、ってのはなんとなく (?) 理解できてるんですが、これを云々してるのが Mapper というクラスなのか。そしてそれを云々してるのが map というメソド。
がしかし、map 呼び出してるのって lib/redmine/plugin.rb なんですがこれって一体内でしょ。
# Adds an item to the given +menu+. # The +id+ parameter (equals to the project id) is automatically added to the url. # menu :project_menu, :plugin_example, { :controller => 'example', :action => 'say_hello' }, :caption => 'Sample' # # +name+ parameter can be: :top_menu, :account_menu, :application_menu or :project_menu # def menu(menu, item, url, options={}) Redmine::MenuManager.map(menu).push(item, url, options) end alias :add_menu_item :menu
これがどこから呼び出されておるか分からんな。つうか、controller と view の上っつらをなでてるだけであんまりきちんと掘れていない感満点なんスけど、まだ最初だからいいよねとかorz
さすがにマルチで色々ヤり杉かなぁ。。