ビュー画面の共通化にはrenderメソッドのパーシャルオプション(パーシャルテンプレート)を使います。複数のテンプレートに自由に埋め込める部分テンプレートです。通常のテンプレートと区別するためにアンダースコア「_」で始まるテンプレートをパーシャルとしています。
パーシャルテンプレートの作り方
_(ファイル名).html.slimという先頭に_(アンダースコア)を付けたファイルを作成します。その中に共通化したいHTMLパーツを記述します。
引数の渡し方
なお、モデルオブジェクト等をHTMLに渡したい場合は呼び出すHTML側からローカル変数を渡してもらいそれをそのまま使うことになります。
レイアウト画面の大枠を共通化する。
パーシャルと違ってヘッダーやサイドバー等のテンプレートの外側を共通化したい場合に使います。Railsのアプリを作成した時点では「application.html.slim」がレイアウトになっています。その他レイアウトを作成したい場合は「app/views/layouts」に新しいテンプレートを配置します。
呼び出し方
呼び出す側のHTMLから下記のように記述します。
1 |
= render partial: 'パーシャルテンプレート名', locals: { パーシャル内のローカル変数(例:user:@user)} |
localsオプション
ローカル変数をパーシャルテンプレートに渡しています。例で言えばインスタンス変数「@user」をパーシャル内のローカル変数userとして渡す形になります。もちろん、パーシャルテンプレート内からも直接インスタンス変数を参照することはできますが、明示的にローカル変数として渡すことで依存性が低く再利用性が高いパーシャルを作成することが可能になります。
objectを使った記述方法
1 |
= render partial: 'パーシャルテンプレート名',object: { パーシャル内のローカル変数(例:@user)} |
objectオプションを使えば、パーシャル名(ファイル名のアンダースコアを抜いた名前)と同じ名前のローカル変数をパーシャルに対して渡すことも可能です。
さらなる簡略化
「パーシャル名」と「インスタンス変数名」が同じであれば下記のように簡略化することも可能です。
1 |
= render @インスタンス変数名 |
共通化の注意点
早すぎる共通化や過度な共通化は逆にメンテナンス性を下げてしまう可能性があるのでちゃんと用途の見通しを持って共通化して良いかは考えるようにしましょう。
ロジックの共通化
HTMLの共通化以外にロジックの共通化も考えられます。
- カスタムヘルパーに共通処理を記述する。
- Decoratorパターンでモデル固有の表示ロジックを分離する。
カスタムヘルパーに共通処理を記述
app/helpers下に一つ一つモジュールとして格納します。
実装のポイント
- 一つ一つのヘルパーはできるだけ小さく作り何でもやろうとしないこと。
- 特定モデルに依存する処理はカスタムヘルパーに含めないこと。
例
- データを加工して表示用文字列を作る等
Decoratorパターンにモデル固有の表示ロジックを分離する。
HtmlBuilderとは?
HTMLソースの生成に特化したモジュールです。
メリット
ERB等のviewテンプレートに組み込むとソースの整理整頓を押し進めることが可能になりリファクタリングがしやすくなります。例えば、重複しているHTML部分を抽出して呼び出すだけでソースが読みやすくなり機能の追加や、バグ対応等がしやすくなります。
デメリット
独自の記法を用いているためまだ慣れていない人にとっては非常に読みづらいコードとなりまし、開発工数がかかります。デザイナーが作成したHTMLをプログラマーが変換する作業が発生するので大変ですし、知らない人があとで見た際に普通のHTMLとは異なるのでキャッチアップに時間がかかってしまいます。デメリットを考慮した上で導入するかは都度判断すると良いでしょう。
Rails内に配置するディレクトリ
1 |
app/lib |
実装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
module HtmlBuilder def conv_html(tag_name = nil, options = {}) root = Nokogiri::HTML::DocumentFragment.parse("") Nokogiri::HTML::Builder.with(root) do |doc| if tag_name doc.method_missing(tag_name, options) do yield(doc) end else yield(doc) end end root.to_html.html_safe end end |
viewヘルパーにモジュールをインクルードします。
1 2 3 |
module ApplicationHelper include HtmlBuilder end |
viewからの呼び出し
1 2 3 4 5 |
conv_html do |c| c.div(class:"test") do c.text "テストです。" end end |
上記のようなものをviewに記述したら下記のようなソースが生成されます。
1 |
<div class="test">テストです。</div> |
この記事へのコメントはありません。