render_if_present helper作った

# いつ使う？

RailsのViewで、特定の値が存在する時にのみpartialを表示したい場合、if文が出てくるとHTMLとしての見通しが悪くなって嫌だ！という時に役に立つんじゃないかと。
デフォルトの仕様として、メソッド名と同じpartialファイルを探索して、メソッド名と同じローカル変数に値をセットするので、規則に沿っておけばだいぶ短く書けるのがメリットです。

こういうケース

```erb
<% if @shop.page_design.shop_top_main_image.present? %>
  <%= render :shop_top_main_image, locals: { shop_top_main_image: @shop.page_design.shop_top_main_image } %>
<% end %>
```

# Rubygemsに登録しました

ヘルパー => 家政婦 => [kaseifu](https://rubygems.org/gems/kaseifu)
今後も便利メソッドを追加していく予定。

J( 'ｰ`)し< ごめんくださいませー

# 使い方

## 基本形

```erb
<%= render_if_present :shop_top_main_image, in: @shop.page_design %>
```

## partialファイルのパスを変えたいケース

partialファイルのパスのみを差し替える。

```erb
<%= render_if_present :shop_top_main_image, in: @shop.page_design, partial: '/shop/image' %>
```

## 共通のpartialファイルを使いたいケース

上記の例との違いは、partialファイルパスおよびローカル変数名の両方が、asで指定した値になる。partialと組み合わせれば、任意のpartialファイルパスを指定する事も可能。

```erb
<%= render_if_present :shop_top_main_image, in: @shop.page_design, as: :shop_image %>
```

## localsを追加で渡したいケース

renderメソッドのlocalsと同じ。

```erb
<%= render_if_present :shop_top_main_image, in: @shop.page_design, locals: { shop_name: @shop.name } %>
```

# コード

```rb
module ApplicationHelper
  # Render partial if the given method is present as the receiver's method.
  #
  # You can render only when @shop.page_design.shop_top_main_image is present.
  #   <%= render_if_present :shop_top_main_image, in: @shop.page_design %>
  # same as
  #   <% if @shop.page_design.shop_top_main_image.present? %>
  #     <%= render :shop_top_main_image, locals: { shop_top_main_image: @shop.page_design.shop_top_main_image } %>
  #   <% end %>
  #
  # You can pass different path of partial.
  #   <%= render_if_present :shop_top_main_image, in: @shop.page_design, partial: 'image' %>
  # same as
  #   <% if @shop.page_design.shop_top_main_image.present? %>
  #     <%= render :image, locals: { shop_top_main_image: @shop.page_design.shop_top_main_image } %>
  #   <% end %>
  #
  # You can use different name as a local variable name in the partial
  #   <%= render_if_present :shop_top_main_image, in: @shop.page_design, as: :shop_image %>
  # same as
  #   <% if @shop.page_design.shop_top_main_image.present? %>
  #     <%= render :shop_image, locals: { shop_image: @shop.page_design.shop_top_main_image } %>
  #   <% end %>
  #
  # You can pass more locals
  #   <%= render_if_present :shop_top_main_image, in: @shop.page_design, locals: { shop_name: @shop.name } %>
  # same as
  #   <% if @shop.page_design.shop_top_main_image.present? %>
  #     <%= render :shop_top_main_image, locals: { shop_top_main_image: @shop.page_design.shop_top_main_image, shop_name: @shop.name } %>
  #   <% end %>
  def render_if_present(method, in: nil, as: nil, **options)
    # "in" is special keyword so need to use local_variable_get to get value
    receiver = binding.local_variable_get(:in)

    raise ArgumentError, 'missing keyword: in' if receiver.nil?

    # If receiver doesn't respond to the given method, render nothing
    return '' unless receiver.respond_to?(method)

    key = (as || method).to_sym
    value = receiver.send(method)

    # If given method return blank, render nothing
    return '' if value.blank?

    # If partial file name is already exist use it else use key.
    options[:partial] ||= key.to_s

    options[:locals] ||= {}
    options[:locals].merge!(key => value)

    render options
  end
end
```

キーワード引数使うと、スッキリ書けて気持ちがいい。