Redmine PluginのViewの拡張ポイント（View hook）がどこにあるか？を列挙する

# これは何？
RedmineのPluginでは、Hookと呼ばれる既存のRedmineへの拡張ポイントを定義できる。
Hookは、Controller hooks、Helper hooks、Model hooksの4種類ある。
詳しくは、[公式Wiki](http://www.redmine.org/projects/redmine/wiki/Hooks)参照ください。

今回は、View hooksのみに着目して拡張ポイントがどこにあるかを解説する。

# 拡張ポイントの一覧

[公式Wiki](http://www.redmine.org/projects/redmine/wiki/Hooks_List)によると45箇所ある。一覧にある「:"view_custom_fields_form_{@custom_field.type.to_s.underscore}"」を除いた44箇所がどこにあるか列挙してみた。画像では44箇所すべて網羅できていないかも・・・。そして黒文字にしてしまったので、見づらい。

![Redmine1.png](https://qiita-image-store.s3.amazonaws.com/0/39825/fdfe23ac-8729-5a7f-c3ed-0a4e8fd7c0a4.png)
![Redmine2.png](https://qiita-image-store.s3.amazonaws.com/0/39825/0eb4457e-986b-af27-237d-e579d221fe0c.png)
![Redmine3.png](https://qiita-image-store.s3.amazonaws.com/0/39825/f7afa8fc-d031-2db7-0803-c21be0bf0588.png)
![Redmine4.png](https://qiita-image-store.s3.amazonaws.com/0/39825/add3d181-eabf-fd6b-f95c-5ff0a858cb10.png)
![Redmine5.png](https://qiita-image-store.s3.amazonaws.com/0/39825/2cd3c2fc-8aef-f129-9496-2b4e8502c813.png)
![Redmine6.png](https://qiita-image-store.s3.amazonaws.com/0/39825/fb7c21c2-7d65-25de-ff82-b0b22f563729.png)
![Redmine7.png](https://qiita-image-store.s3.amazonaws.com/0/39825/662933d1-ac4e-2fe0-e4e3-e8cc8bbcf0e0.png)
![Redmine8.png](https://qiita-image-store.s3.amazonaws.com/0/39825/c50272ea-2537-1a77-2785-91f09472810f.png)
![Redmine9.png](https://qiita-image-store.s3.amazonaws.com/0/39825/756415cb-70eb-3702-2969-8805a700d7c2.png)
![Redmine10.png](https://qiita-image-store.s3.amazonaws.com/0/39825/590937e1-a58b-e1fe-77bf-2c8c680c93aa.png)
![Redmine11.png](https://qiita-image-store.s3.amazonaws.com/0/39825/8d4363c2-2063-f954-d881-947768684af4.png)
![Redmine12.png](https://qiita-image-store.s3.amazonaws.com/0/39825/5f30c20a-be9e-88f7-5f78-f2e14c10fb06.png)

# 試したコード
```rb:FooHook

class FooHook < Redmine::Hook::ViewListener
  def view_account_left_bottom(context={})
    html = ''
    html << '<p><b>view_account_left_bottom</b></p>'
    return html
  end


  def view_account_right_bottom(context={})
    html = ''
    html << '<p><b>view_account_right_bottom</b></p>'
    return html
  end


  def view_account_login_top(context={})
    html = ''
    html << '<p><b>view_account_login_top</b></p>'
    return html
  end


  def view_account_login_bottom(context={})
    html = ''
    html << '<p><b>view_account_login_bottom</b></p>'
    return html
  end


  def view_custom_fields_form_upper_box(context={})
    html = ''
    html << '<p><b>view_custom_fields_form_upper_box</b></p>'
    return html
  end


  def view_issue_statuses_form(context={})
    html = ''
    html << '<p><b>view_issue_statuses_form</b></p>'
    return html
  end


  def view_issues_bulk_edit_details_bottom(context={})
    html = ''
    html << '<p><b>view_issues_bulk_edit_details_bottom</b></p>'
    return html
  end


  def view_issues_edit_notes_bottomAppends(context={})
    html = ''
    html << '<p><b>view_issues_edit_notes_bottomAppends</b></p>'
    return html
  end


  def view_issues_form_details_bottom(context={})
    html = ''
    html << '<p><b>view_issues_form_details_bottom</b></p>'
    return html
  end


  def view_issues_history_journal_bottom(context={})
    html = ''
    html << '<p><b>view_issues_history_journal_bottom</b></p>'
    return html
  end


  def view_issues_show_details_bottom(context={})
    html = ''
    html << '<p><b>view_issues_show_details_bottom</b></p>'
    return html
  end


  def view_issues_sidebar_issues_bottom(context={})
    html = ''
    html << '<p><b>view_issues_sidebar_issues_bottom</b></p>'
    return html
  end


  def view_issues_sidebar_planning_bottom(context={})
    html = ''
    html << '<p><b>view_issues_sidebar_planning_bottom</b></p>'
    return html
  end


  def view_issues_sidebar_queries_bottom(context={})
    html = ''
    html << '<p><b>view_issues_sidebar_queries_bottom</b></p>'
    return html
  end


  def view_issues_context_menu_start(context={})
    html = ''
    html << '<p><b>view_issues_context_menu_start</b></p>'
    return html
  end


  def view_issues_context_menu_end(context={})
    html = ''
    html << '<p><b>view_issues_context_menu_end</b></p>'
    return html
  end


  def view_issues_new_top(context={})
    html = ''
    html << '<p><b>view_issues_new_top</b></p>'
    return html
  end


  def view_issues_show_description_bottom(context={})
    html = ''
    html << '<p><b>view_issues_show_description_bottom</b></p>'
    return html
  end


  def view_issues_move_bottom(context={})
    html = ''
    html << '<p><b>view_issues_move_bottom</b></p>'
    return html
  end


  def view_journals_notes_form_after_notes(context={})
    html = ''
    html << '<p><b>view_journals_notes_form_after_notes</b></p>'
    return html
  end


  def view_journals_update_rjs_bottom(context={})
    html = ''
    html << '<p><b>view_journals_update_rjs_bottom</b></p>'
    return html
  end


  def view_layouts_base_body_bottom(context={})
    html = ''
    html << '<p><b>view_layouts_base_body_bottom</b></p>'
    return html
  end


  def view_layouts_base_content(context={})
    html = ''
    html << '<p><b>view_layouts_base_content</b></p>'
    return html
  end


  def view_layouts_base_html_head(context={})
    html = ''
    html << '<p><b>view_layouts_base_html_head</b></p>'
    return html
  end


  def view_layouts_base_sidebar(context={})
    html = ''
    html << '<p><b>view_layouts_base_sidebar</b></p>'
    return html
  end


  def view_my_account(context={})
    html = ''
    html << '<p><b>view_my_account</b></p>'
    return html
  end


  def view_my_account_contextual(context={})
    html = ''
    html << '<p><b>view_my_account_contextual</b></p>'
    return html
  end


  def view_projects_form(context={})
    html = ''
    html << '<p><b>view_projects_form</b></p>'
    return html
  end


  def view_projects_roadmap_version_bottom(context={})
    html = ''
    html << '<p><b>view_projects_roadmap_version_bottom</b></p>'
    return html
  end


  def view_projects_settings_members_table_header(context={})
    html = ''
    html << '<p><b>view_projects_settings_members_table_header</b></p>'
    return html
  end


  def view_projects_settings_members_table_row(context={})
    html = ''
    html << '<p><b>view_projects_settings_members_table_row</b></p>'
    return html
  end


  def view_projects_show_left(context={})
    html = ''
    html << '<p><b>view_projects_show_left</b></p>'
    return html
  end


  def view_projects_show_right(context={})
    html = ''
    html << '<p><b>view_projects_show_right</b></p>'
    return html
  end


  def view_projects_show_sidebar_bottom(context={})
    html = ''
    html << '<p><b>view_projects_show_sidebar_bottom</b></p>'
    return html
  end


  def view_repositories_show_contextual(context={})
    html = ''
    html << '<p><b>view_repositories_show_contextual</b></p>'
    return html
  end


  def view_timelog_edit_form_bottom(context={})
    html = ''
    html << '<p><b>view_timelog_edit_form_bottom</b></p>'
    return html
  end


  def view_settings_general_form(context={})
    html = ''
    html << '<p><b>view_settings_general_form</b></p>'
    return html
  end


  def view_users_memberships_table_header(context={})
    html = ''
    html << '<p><b>view_users_memberships_table_header</b></p>'
    return html
  end


  def view_users_memberships_table_row(context={})
    html = ''
    html << '<p><b>view_users_memberships_table_row</b></p>'
    return html
  end


  def view_users_form(context={})
    html = ''
    html << '<p><b>view_users_form</b></p>'
    return html
  end


  def view_versions_show_bottom(context={})
    html = ''
    html << '<p><b>view_versions_show_bottom</b></p>'
    return html
  end


  def view_versions_show_contextual(context={})
    html = ''
    html << '<p><b>view_versions_show_contextual</b></p>'
    return html
  end


  def view_welcome_index_left(context={})
    html = ''
    html << '<p><b>view_welcome_index_left</b></p>'
    return html
  end


  def view_welcome_index_right(context={})
    html = ''
    html << '<p><b>view_welcome_index_right</b></p>'
    return html
  end
end

```