阿部です。
UNC形式のパスをクリップボードにコピーするRedmineプラグイン を開発しました。 それを通してRedmineのプラグインを一から作る方法について学んだので、その内容を紹介します。
作ったときの私の知識レベルが以下なので、そのくらいの方であれば参考になる内容だと思います。
- Redmineは普段利用している
- RedmineはRuby on Railsで開発されているらしい
- コードは読んだことがない
- Ruby on Rails自体は初心者
- Redmineのプラグイン開発の経験もなし
はじめに
今回開発したプラグインはUNC形式のパスをクリックでクリップボードにコピーできるようにするものです。 そのようにすることでUNC形式のファイルパスを開くまでのステップを少なくすることが狙いです。
近年はセキリティ上の理由からブラウザで file://
URLへのアクセスに制限があるため、この補助機能でファイルが開きやすくなります。
もう少し具体的に機能の説明をすると、
\\server\path\to\file
といった文字列のUNC形式のパスを、
以下のキャプチャにあるクリックでパスをコピーするリンクに自動で変換して表示します。
このRedmineのプラグインではそのような表示文字列の自動変換以外にもできることはいろいろありますが、 本記事では「Redmineの投稿内容を加工して表示」するプラグインを一から作る方法について紹介します。
流れ
- Redmine本体を動かす
- プラグインの雛形生成
- プラグイン情報の更新
- プラグインの実装
1. Redmine本体を動かす
今回の本題ではありませんので、Redmineを起動するまでのコマンドの列挙に留めます。 以下の通り実行することでRedmineが起動しブラウザで確認できます。
git clone --depth 1 https://github.com/redmine/redmine.git
cd redmine
cat <<EOF > config/database.yml
development:
adapter: sqlite3
database: db/redmine.sqlite3
EOF
bundle install
bin/rails generate_secret_token
bin/rails db:migrate
REDMINE_LANG=en bin/rails redmine:load_default_data
bin/rails server
2. プラグインの雛形生成
以下のコマンドでプラグインの雛形を生成します。
bin/rails generate redmine_plugin <plugin_name>
Redmine本体を起動したディレクトリで実行します。
bin/rails generate redmine_plugin UNC
create plugins/unc/app
create plugins/unc/app/controllers
create plugins/unc/app/helpers
create plugins/unc/app/models
create plugins/unc/app/views
create plugins/unc/db/migrate
create plugins/unc/lib/tasks
create plugins/unc/assets/images
create plugins/unc/assets/javascripts
create plugins/unc/assets/stylesheets
create plugins/unc/config/locales
create plugins/unc/test
create plugins/unc/test/fixtures
create plugins/unc/test/unit
create plugins/unc/test/functional
create plugins/unc/test/integration
create plugins/unc/test/system
create plugins/unc/README.rdoc
create plugins/unc/init.rb
create plugins/unc/config/routes.rb
create plugins/unc/config/locales/en.yml
create plugins/unc/test/test_helper.rb
plugins
ディレクトリ以下に生成されます。
3. プラグイン情報の更新
init.rb
を開発するプラグインに合わせて更新します。
以下の内容に更新しました。
Redmine::Plugin.register :unc do
name 'UNC plugin'
author 'ClearCode Inc.'
description 'Improve UNC format path accessibility'
version '0.0.1'
url 'https://gitlab.com/redmine-plugin-unc/redmine-plugin-unc'
author_url 'https://gitlab.com/clear-code'
end
4. プラグインの実装
すべての投稿内容にあるUNC形式のパスを変換したいので、ApplicationHelper#parse_non_pre_blocks
を拡張して対応することにしました。
ApplicationHelper#parse_non_pre_blocks
は、表示するHTMLのうち
<pre>
タグ以外の要素(= マークアップ言語としてMarkdownを使っている場合は ```
、 `
で囲まれたところ以外)に対して
ブロックで受け取った変換処理を行うメソッドです。
そこにUNC形式のパスを変換する処理を追加する方針です。
このメソッドを Module#prepend
を使って拡張します。
(Redmineのドキュメントにある
Plugin Internals > Extending the Redmine Core
に相当する方法です。)
実際のコードが30行もないので掲載して簡単に解説します。
module Unc
module ApplicationHelperMixin
def link_unc_path(path)
link_to_function(
"(#{l(:copy_unc_path)}) #{path}",
'copyTextToClipboard(this)',
class: 'icon icon-copy-link',
data: {'clipboard-text' => path}
)
end
def parse_unc_paths(text)
text.gsub!(/"(\\\\.+?)"|\\\\[^\s<]+/) do |matched|
link_unc_path($1 || matched)
end
end
def parse_non_pre_blocks(text, obj, macros, options={})
super do |txt|
yield txt
parse_unc_paths(txt)
end
end
end
end
ApplicationHelper.prepend(Unc::ApplicationHelperMixin)
link_unc_path
- クリップボードへコピーするリンクのHTMLを生成するメソッド
- クリップボードへコピーするJavaScriptがRedmineに含まれていたので活用
- Redmineにある類似のメソッドを参考にしました
ApplicationHelper#copy_object_url_link
parse_unc_paths
- 投稿テキストに含まれるUNC形式のパスを
link_unc_path
が返すHTMLに置換
- 投稿テキストに含まれるUNC形式のパスを
parse_non_pre_blocks
super
が受け取ったブロックを実行し、その後でparse_unc_paths
の処理を実行
ApplicationHelper.prepend(Unc::ApplicationHelperMixin)
ApplicationHelper
にUnc::ApplicationHelperMixin
を追加して、parse_non_pre_blocks
を上書き
最後に Unc::ApplicationHelperMixin
の読み込みを init.rb
へ追加して完了です。
追加後の init.rb
は以下の通りです。
Redmine::Plugin.register :unc do
name 'UNC plugin'
author 'ClearCode Inc.'
description 'Improve UNC format path accessibility'
version '0.0.1'
url 'https://gitlab.com/redmine-plugin-unc/redmine-plugin-unc'
author_url 'https://gitlab.com/clear-code'
end
# Load.
Unc::ApplicationHelperMixin
最後の1行がポイントで Unc::ApplicationHelperMixin
により
lib/unc/application_helper_mixin.rb
が読み込まれ、
その中で ApplicationHelper.prepend(Unc::ApplicationHelperMixin)
が実行されます。
その結果、このプラグインで変更した処理がRedmineに組み込まれます。
まとめ
UNC形式のパスをクリップボードにコピーするRedmineプラグインを一から作る方法を紹介しました。 「Redmineの投稿内容を加工して表示」するプラグインを開発するときに役立つと思います。
違う機能のプラグインを開発する場合は方法が変わりますので、 Plugin Tutorial を参考にご対応ください。
なお、この機能はクリアコードが提供しているRedmineサポート契約の中で開発しました。 クリアコードが提供するRedmineサポートではお客さんが必要としている機能を理解した上で 汎用的なプラグインとして対応することが多いです。 その際、プラグインは自由なソフトウェアとして開発し広く公開します。 汎用的な機能のため、お客さんの機密情報などが含まれることがなく、 お客さんにとってデメリットはありません。 また他のお客さんでも使うことになったら、メンテナンス費用を 按分できるコストメリットもあります。
プラグインではなくRedmine本体を改良した方がよさそうな場合もあります。 その時はお客さんが使っているRedmineにパッチを当ててもらうのではなく、 Redmine本体に機能を提案してRedmine本体に取り込んでもらえるようにします。 自分たちでパッチを当てるよりもRedmine本体に入っていた方がアップデートが楽になり、 メンテナンスコストが下がるからです。 ただ、Redmine本体の開発をコントロールすることはできないので、 一時的にプラグインで対処したりパッチを当ててもらうということはあります。
そのようなRedmineサポートがよい方はお問い合わせフォームよりご連絡ください。
参考: Redmineのドキュメント
- Redmine本体のインストール
- プラグイン開発のチュートリアル