torutkのブログ

ソフトウェア・エンジニアのブログ

Redmine 4.0(Rails 5.1)でのプラグイン作成について(5)

id:torutk:20180530 の続き。

Glossaryプラグインの再構築でファイル添付機能を実装しようとこの数日格闘していました。
書籍「Redmine Plugin Extension and Development」は4章にファイル添付の解説があり、基本そのままたどってみたのですがいくつか落とし穴(書籍の記述を見落としたものもあり)があって、長引いています。

ファイル添付できない

書籍では、コントローラーのupdateメソッドに次の記述を追加するサンプルが記載されています。

def update
  # ...
  if @article.update_attributes(params[:article])
    @article.save_attachments(params[:attachments])
    render_attachment_warning_if_needed(@article)

Glossaryプラグインの再構築では、updateメソッドで最初次のように記述しましたが、ファイルが添付されませんでした。

def update
  @term.attributes = glossary_term_params
  if @term.save
    @term.save_attachments params[:attachments]
    render_attachment_warning_if_needed(@term)

モデルのsaveの後にsave_attachmentsを呼ぶのがまずいのかもと、試行錯誤的に順番を入れ替えてみたところ、ファイルが添付されました。次のコードです。

def update
  @term.attributes = glossary_term_params
  @term.save_attachments params[:attachments]
  if @term.save
    render_attachment_warning_if_needed(@term)

Redmine本体で添付ファイルを扱っている個所を探してみたところ、ドキュメントコントローラーに類似コードがありました。

  • app/controllers/documents_controller.rb
def create
   :
  @document.safe_attributes = params[:document]
  @document.save_attachments(params[:attachments])
  if @document.save
    render_attachment_warning_if_needed(@document)

このコードとほぼ同じなので、試行錯誤の結果は妥当かと思います。

権限の名前が不一致で添付ファイルのダウンロードが403エラー

書籍ではモデルクラスに次の1行を書くサンプルが記載されています。

acts_as_attachable

その後ろの本文の中でデフォルトの権限はモデル名に基づき生成されるとの記述があったのですが読み落としており、添付したファイルをクリックすると403エラーとなってしまいました。Redmineのコードにputs文で値を出しつつ原因を調べたところ、モデル名から生成される権限名(GlossaryTermモデルならview_glossary_term)と、Glossaryプラグインの設定(init.rb)で定義した権限名(今回はview_glossaryと指定)が違っていたためと判明しました。それから再度書籍を見ると、ちゃんと書いてありました。見落としでした。ただ、Redmineのコードを追いかけていたので、書籍(Redmine 2.x)の記載と今のコード(Redmine 3.4)では権限の指定種類が1つ増えている違いがあるのが分かったのがせめてもの収穫でした。

acts_as_attachable view_permission: :view_glossary,
  edit_permission: :manage_glossary, delete_permission: :manage_glossary

ファイル添付が成功しても、失敗のメッセージ表示が出る

コントローラーでファイル添付の際に失敗があれば警告メッセージを表示する次の呼び出しを書いています。

render_attachment_warning_if_needed(@term)

ところが、なぜかファイル添付が成功していても、警告メッセージが表示されてしまいます。
調べていくと、フォームからファイル添付時に送るパラメーターにゴミが含まれていることが分かりました。次は編集時にファイルを1つ添付した場合にフォームから送られる添付ファイルのパラメータです。

"attachments"=>{
  "1"=>{"filename"=>"f022.png", "description"=>"aaa", "token"=>"38.8e4d1dd26bde5a3b4c0f79c186713c1f6922ce57a1d42dca1e9dcbaab5604f84"},
  "dummy"=>{"file"=>""}
}

なぜか、キー"dummy"が付いており、1つのファイルを添付し他のに関わらず2つのキーバリューが生成されています。添付ファイル1件の処理が終わった時点で、残りが1件と誤認識され警告メッセージが表示されていると思われます。

書籍に言及はなく、ググっていると次のブログに解決方法を見つけました。
【Redmine拡張】Redmineの添付ファイル機能を使う : ほんにゃら重工

曰く

フォームはmultipartをONにしておく必要あり。

edit.html.erbを修正しました。htmlをキーにmultipart指定を追加しています。

<%= labelled_form_for @term, url: project_glossary_term_path, html: {multipart: true} do |f| %>

その他

WSLのOpenSUSE環境が壊れた?

主にWSLのOpenSUSEプラグインの作成を行ってきましたが、今日、bundle execでrailsコマンドを実行しようとすると、rubyがエラー(pthread のinvalid argumentエラー)になってしまいました。

結局、OpenSUSEMicrosoft Storeアプリ)をアンインストールしてインストールし直しました。