Railsの小技:パーシャルのrenderにブロックを取れるの知ってた?

More than 5 years have passed since last update.


例えばこんなとき・・・

例えばこんなビューがあったとします。simple_formを使っているとこんなビミョーなマークアップ、ありがちな気がします。

// フォームの途中で・・・

= f.input :event_name

.row.message
.col-md-3
.col-md-9
.hint
%p イベント名はトップページのイベント一覧にも表示されます。

= f.input :event_type, as: :radio_buttons, item_wrapper_class: 'inline'

.row.message
.col-md-3
.col-md-9
.hint
%dl
%dt 飲み会
%dd 飲みに行く人数をあらかじめ決めて店を予約する必要があります。
%dt 勉強会
%dd 数人のスピーカーと、数人のLTを用意する必要があります。
%dt もくもく会
%dd 誰も一言も喋ることなく、もくもくと作業する場所を用意する必要があります。

以下のようなマークアップが重複していて嫌な感じがしますよね。DRYじゃなくて発狂しそうです。

.row.message

.col-md-3
.col-md-9
.hint
%p イベントの日付は開催日を入力してください。


render layoutを使うとDRYに書ける

こんなパーシャルビューを用意しておいて、


_hint.html.haml

.row.message

.col-md-3
.col-md-9
.hint
= yield

こんな感じで使います。

// フォームの途中で・・・

= f.input :event_name

= render layout: 'hint' do
%p イベント名はトップページのイベント一覧にも表示されます。

= f.input :event_type, as: :radio_buttons, item_wrapper_class: 'inline'

= render layout: 'hint' do
%dl
%dt 飲み会
%dd 飲みに行く人数をあらかじめ決めて店を予約する必要があります。
%dt 勉強会
%dd 数人のスピーカーと、数人のLTを用意する必要があります。
%dt もくもく会
%dd 誰も一言も喋ることなく、もくもくと作業する場所を用意する必要があります。

重複がなくなってスッキリしますね。


引数も設定できる

以下のように書けばパーシャルビューに引数を渡すこともできます。

= render layout: 'hint', locals: { message_id: 'hoge' } do

「引数を渡したいときも、渡したくないときもあるんだよねー」という場合は、以下のようにパーシャルの方で制御するとNameErrorが発生せずに済みます。local_assignsを使うのがポイントです。


_hint.html.haml

:ruby

data_message_id = (local_assigns.has_key? :message_id) ? message_id : nil

.row.message{data: {message_id: data_message_id}}
// ...


ヘルパーで頑張ることもできますが、htmlのマークアップが絡んでくるところは、上手くパーシャルを使う方がスッキリすると思います。