in_place_editorを使ってみる。
今の状態では、CSVリストをフィルターで絞り込み、属性変更の編集ページに移動して、再びCSVリストページに戻ってきた時に、フィルターは解除されてしまう。もう一度同じCSVファイルを見つけるのにフィルターを再設定する必要があり、フィルター条件が複雑だったりすると手間がかかる。そこで考えたのが、ページを切り替えるまでもなく、同じページで修正してajax更新すれば良いのではないかということ。(属性の変更可能な項目はコメント、編集可能フラグ、管理部門のたった3項目だけなので。)
それを実現する方法を調べてみると、Railsでは、in_place_editorをとてもシンプルに利用できるヘルパメソッドが存在する。in_place_editorを使えば、編集したい文字列をクリックすると、その部分だけが入力フォームに変化して、その場で編集することが可能になる。初めて体験した時は、なんだかとても斬新な機能に感じた。早速、CSVサーバーにも取り入れてみた。
基本パターン
- app/views/csvs/_listd.rhtml
- ビュー
- ビューでは、text_fieldと同じ書式で以下のようにすればOK。すでにlistdにはCSVモデルの1レコードが代入されているが、..._field :csv, :file_commentの書式に合わせるため、@csv = listdでルール上必要と思われる変数に代入した。(なんか無駄なことをしている気がするが、良いやり方が他にあるのだろうか?)
...(途中省略)... <%#=h listd.file_comment %> <%# リスト表示の上記コードを以下のように変更した。 %> <% @csv = listd %> <%= in_place_editor_field :csv, :file_comment %> ...(途中省略)...
- app/controllers/csvs_controller.rb
- コントローラー
- コントローラーに以下のように指定すると、in_place_editor_fieldからのパラメータを受け取り、データベースの更新とビューの描画を適切に処理してくれる。
class CsvsController < ApplicationController
in_place_edit_for :csv, :file_comment
...(途中省略)...
-
-
- 上記のように宣言することは、以下のメソッドを定義することと同等である。
- :idには修正したレコードのid、params[:value]には入力した値が代入されている。
-
def set_csv_file_comment
@item = Csv.find(params[:id])
@item.update_attribute('file_comment', params[:value])
render :text => @item.send('file_comment')
end
以上のコードだけで、今までのコメント部分が直接編集可能な状態になる。素晴らしくシンプルな書き方だ。ところが、1つ問題が発生。文字が入力されていないと編集モードに移行できない...。
ブランク項目で編集モードに移行する方法
いろいろな回避方法があるようだが、ここでは以下のようにやってみた。
- コメントの先頭には常に「»」マークを表示する。
- :external_controlオプションで、上記マークのid属性を指定する。
- これで上記マークをクリックすれば、ブランク項目であっても編集モードに移行することが可能になる。
<span class="empty_message" id="file_comment<%= listd.id %>">»</span> <%= in_place_editor_field :csv, :file_comment, {}, :external_control => "file_comment#{listd.id}" %>
CSVサーバーに合わせた調整
その他にもこのような欲求があったので、結局、全部まとめて以下のようになった。
- 「ok」「cancel」ボタンを日本語で表示したい。
- 入力値のサニタイズが必要なのではないか?
- 同じ管理部門のユーザーしか編集できないように制限したい。
- 編集中はテキストエリアを表示したい。(テキストフィールドではカーソルの位置が確認できない表示だったので。)
- :rowsが1ならテキストフィールド
- :rowsが2以上ならテキストエリア
...(途中省略)... <td <%= arranged_class("file_comment") %>> <% listd.file_comment = sanitize(listd.file_comment) %> <% if management_section?(listd.management_section) %> <span class="empty_message" id="file_comment<%= listd.id %>"><%= "»" %></span> <%= in_place_editor_field :csv, :file_comment, {}, :rows => 2, :save_text=>"保存", :cancel_text=>"キャンセル", :external_control => "file_comment#{listd.id}" %> <% else %> <%=h listd.file_comment %> <% end %></td> ...(途中省略)...
参考ページ
以下のページが大変参考になりました。感謝です。
しかし、まだまだ使いこなすためには理解を深める必要がある...。簡単そうだけど、自由に使いこなすには知識が必要だ。