torutkのブログ

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

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

id:torutk:20180527の続きです。

用語一覧表示において、べたに一覧表示する方法と、カテゴリ毎に一覧表示する方法とをラジオボタンで切り替える機能をどのように実装すればよいかを探っています。

アプローチの模索

スタンドアロン(デスクトップ)アプリケーションと違って、Webアプリケーションはサーバー側で表示(HTML)を生成するので、表示設定の変更もいったんサーバーに送って新たに表示を生成することになります。

JavaScriptで表示を制御するとしたら

JavaScriptを駆使して、ブラウザ上で表示を変更することもできないかとアプローチしてみましたが、表示する可能性のあるHTML要素を予め生成しておき、JavaScriptからHTML要素の表示有無を切り替えるといった振る舞いとなり、今回であればべた一覧表示とカテゴリ毎の一覧を両方生成し、どちらを表示するかを切り替えるといった実装になりそうです。
ラジオボタンのコールバックにJavaScriptの関数を指定し、ラジオボタンが押されたら、対応するHTML要素を有効化し、残りを無効化するようなイメージです。

べた一覧表示を、

...
で囲い、カテゴリ毎に一覧表示を、
...
で囲い、JavaScriptにおいて、var not_grouping = document.getElementById("not_grouping")で取得すると、取得した要素のオブジェクトに対し、style.display="none"を設定すると非表示にすることができる模様です。

ちょっと力業過ぎるかと思い、実装には入りませんでした。

フォームで制御するとしたら

ラジオボタンの設定をフォームでサーバーにサブミットし、サーバー側で設定を見てべた一覧表示かカテゴリ毎の一覧表示かを判別してHTMLを生成します。

ここで、Ruby on Rails では通常はモデルクラスを用意し、フォームではそのモデルのインスタンスを指定しインスタンスの属性を新規作成ならcreate、既存の変更ならeditアクションを実行します。

しかし、今回は表示設定なのでモデルクラスはありません。表示設定をデータベース化するならモデルクラスからコントローラークラス、ビューとフルに作ってもよいですが、そこまで頑張らずに済む方法を追求します。

用語コントローラーのindexアクションで、ラジオボタンの設定をリクエストパラメーターに持たせ、indexの描画時にパラメーターに応じてべた一覧表示かカテゴリ毎に一覧表示かを切り替えることとします。

まず、RedmineRuby on Rails)でフォームを実装するAPIとして利用できそうなものを探したところ次が見つかりました。

API 内容
form_for モデルインスタンス用のフォーム
form_tag カスタムURL(モデルインスタンス不要)用のフォーム
form_with Ruby on Rails 5.1から導入され、form_forとform_tagの両者の機能を持ち将来的に置き換わるAPI
labelled_form_for Redmineが提供するform_forのラッパー

今回はモデルクラスとモデルインスタンスを指定せずにフォームを実現したいので、モデルの指定が不要なform_tagまたはform_withを使用します。

form_withについては、従来のform_forとform_tagの機能を兼ね備え、これらを代替するものとしてRails 5.1で導入されました。将来的にはform_forとform_tagはデプリケートとなる予定です(Rails 6あたり)。

form_tagでラジオボタンを設置

書式は、

form_tag(URL [, options]) do
end

といった感じです。

用語一覧のコントローラーのindexアクションはルーティング設定でproject_glossary_termsの末尾に_pathを付けたものになります。
メソッドはデフォルトではpostになってしまうので、明示的にgetを指定しています。

<%= form_tag(project_glossary_terms_path, method: :get) do %>
  <%= radio_button_tag :grouping, 1, @grouping == '1' ? true : false %>
  <%= label_tag 'カテゴリで分類' %>
  <%= radio_button_tag :grouping, 0, @grouping == '0' ? true : false %>
  <%= label_tag '分類なし' %>
  <%= submit_tag '表示' %>
<% end %>

ラベルの指定は不十分かもしれません(ラジオボタンと紐づくラベルを生成するにはさらなる指定が必要な模様)。

form_tagを使用する場合、radio_buttonではなくradio_button_tagを使用するようです。

form_with

これは、用語集プラグイン再構築で実装したので日記では省略します。