Redmineの「XX日前」を「yyyy/MM/dd」日付表現で表示するプラグインを書いた

Redmineのチケットは作成日、更新日をちゃんと残してくれるけど、「XX日前」とか表示されていて分かりづらい気がします。特に古いチケットになると「XXヶ月前」とかなってしまって、いったいいつ発行したのかわからなくなってしまうことがあります。*1

こんな感じです。



やっぱり分かりづらいので見慣れた「yyyy/MM/dd」形式の表示で置き換えるプラグインを作りました。

環境

Redmine 1.0.X で動きます。
以前のバージョンは未確認です。

動作

こんな感じで「yyyy/MM/dd」形式で日付が表示されます。

インストール

1. https://github.com/suer/redmine_absolute_dates からgit cloneして、vendor/plugins に置くか、以下を実行する


ruby script/plugin install git@github.com:suer/redmine_absolute_dates.git
2. Redmineを再起動

技術的な話

Redmine本体の機能を変えるプラグインなので、本体コードの改変が必要になりますが、基本的に本体コードには手を出さないのがRedmine プラグインプログラマの作法です。
ちょっとした魔術が必要です。

日付を表示している部分は以下のような感じです。

<!-- app/view/issues/show.rhtml -->
<p class="author">                                                                                          
  <%= authoring @issue.created_on, @issue.author %>.                                                          
  <% if @issue.created_on != @issue.updated_on %>                                                             
  <%= l(:label_updated_time, time_tag(@issue.updated_on)) %>.                                                 
  <% end %>                                                                                                   
</p> 

authoring メソッドで 「XXXがYYY日前に作成しました」と表示し、time_tagメソッドで更新日時を「XXX日前」に変換して表示しているようです。
ここで authoringメソッドは

# app/helpers/application_helper.rb
module ApplicationHelper
  def authoring(created, author, options={})                                                                        
     l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created))          
  end
end

のように、こちらでもやはり time_tagメソッドを使用しています。

なので authoring メソッドと、 time_tagメソッドを書き換えてやる必要があります。

プラグインでは以下のようなモンキーパッチをあてます。
alias_method_chain で日付の文字列を変更するようにラップしています。

module AbsoluteDateHelperPatch
  def self.included(base) # :nodoc:
    base.send(:include, InstanceMethods)

    base.class_eval do
      alias_method_chain :authoring, :absolute_date
      alias_method_chain :time_tag, :absolute_date
    end
  end

  module InstanceMethods
    # Adds a rates tab to the user administration page
    def authoring_with_absolute_date(created, author, options={})
      l(options[:label] || :label_added_absolute_time_by, :author => link_to_user(author), :age => time_tag(created))
    end

    def time_tag_with_absolute_date(time)
      text = format_date(time)
      if @project
        link_to(text, {:controller => 'projects', :action => 'activity', :id => @project, :from => time.to_date}, :title => text)
      else
        content_tag('acronym', text, :title => text)
      end
    end

  end
end

もとの動作を完全に捨てているので、単にalias_methodでもいいと思います。
alias_method_chain にしてるのは単に使ってみたかったからです:)
alias_method_chain の動作はメタプログラミングRubyを読めば分かると思います。

Redmine本家でも本体のコードを上書きするようプラグインを書く場合は、alias_method_chain でラップするといい、と言っています。
http://www.redmine.org/wiki/redmine/Plugin_Internals#Wrapping-an-existing-method

:label_added_absolute_time_by などはプラグイン内のローカライズ用のファイル(config/locales/ja.yaml) に書いておきます。(もとのやつを使うと yyyy/MM/dd前 とか表示されていやなので)

これをプラグインの init.rb で ApplicationHelperにincludeしてやります

  ApplicationHelper.send(:include, AbsoluteDateHelperPatch)


メタプログラミングRuby
Paolo Perrotta
アスキー・メディアワークス
売り上げランキング: 24889
おすすめ度の平均: 5.0
5 おもしろい!「好きこそ物の上手なれ」かな?

*1:マウスオーバーで表示されるTipには日付が表示されますが....