[Rails][メモ]Cells - partialをcontrollerとview共にまとめるGem 


Railsでviewを作成する際、部分テンプレートとして
partialメソッドを利用しない日はないと思います。

ですが、このpartial、あくまでビューに特化した機能なので、
ロジックをwrapして部分テンプレート化しようとすると、非常に煩雑。

以下に想定される利用シーンとcellを利用した解決策をメモがてら残しておきます。


# Cellsの利用シーンの具体例

- ログインポップアップ
- サイドメニューのランキング表示
- 最近流行りのフッダーにお問い合わせフォームを置くやつとか。

など、全てのページでよく使われる部分パーツなどが
具体的な利用シーンで上げられます。


たとえばログインポップアップで言うと、
以下のようなpartialの読み出しをします。

```haml:dashboard.html.haml
- unless user_signed_in?
  .header
    .header__login-button
      = link_to 'ログインする', 'javascript:void(0);'
= render partial: 'popup_login'
```

＊あ、上記コードは ** dashboard以外にも、あらゆるページに存在している** という前提で！


で、partialのpopup_loginの中身は以下。

```haml:_popup_login.html.haml
- unless user_signed_in?
  .popup-login //cssはデフォルトdisplay:none;
    = form_for(@user, url:user_session_path) do |f|
      %dl
        %dt= f.label :email
        %dd= f.email_field :email
        %dt= f.label :password
        %dd= f.password_field :password
      = f.submit 'ログインする'
   :javascript
     $('.header__login-button a').click(function(){
       $('.popup-login').css({ 'display' : 'block'});
     });
```

といった感じ。'ログインする'というリンクをクリックすると、
jsで上記のポップアップが出現するという仕組みです。(cssの記述はここでは省きます。)

ここで問題が。
haml:_popup_login.html.haml内の```@user```を、どこで生成するのか、という問題です。

コントローラで@userに関する記述を書かないと上記エラーが発生します。
ではこれを書くのは、applicationコントローラー？
まさかまさかの毎回それぞれのページにactionごとに設定する？(いやいやいや！ナシっしょ)


# applicationコントローラに書いた場合（やらない方がいい例）


愚直に考えると…

```ruby:app/controller/application_controller.rb
class ApplicationController < ActionController::Base
  before_action: :pre_load
  
  def pre_load
    @user = User.new unless current_user.present?
  end
end
```

か。
ただ、今回はログイン周りだけのため簡素だが、
例えばランキング機能とか、サイトコメント機能？とか増えていくと、
ここが肥大していく。

また、通常のrailsのようにactionとviewの関連がわからず、
ぱっと見viewと関連が「疎」なため管理しづらい。

また、後々@userを読みたくないページがあるんだけどとかの場合、
そのページでbefore_actionをexpectしなくちゃいけないとかになってくると、
全てのコントローラーでこのメソッドを意識してロードしなくちゃいけないとか
結構めんどくなる。

ここででる本音は、viewとロジック(controller)をワンセットでパッケージ化してくれると
便利なんだどなぁという心の声。

そしたらありました、便利なGemが。
それがCellsです。なんか定番みたいで今更っすけど…　メモがてら。


# Cellsとは。

例えばさっきのhaml:dashboard.html.hamlのコード。

```haml:dashboard.html.haml
= render partial: 'popup_login'
```

がありましたが、

```haml:dashboard.html.haml
= render_cell :popup_login, :show
```

ってな感じで書くことで、
ロジックとviewをセットで読みだしてくれるという便利Gem。

render_cellした:popup_loginがどうなっているかというと
こんな感じに設置された```show.html.haml```と```popup_login_cell.rb```がワンセットになって
呼び出されます。

```ディレクトリ
/app
  /assets
  /cells
     /popup_login
       show.html.haml
     popup_login_cell.rb
```

```haml:app/cells/popup_login_cell.rb
class PopupLoginCell < Cell::Rails
  def show
    @user = User.new unless current_user.present?
    render
  end
end

```

```haml:app/cells/popup_login/show.html.haml
- unless user_signed_in?
  .popup-login //cssはデフォルトdisplay:none;
    = form_for(@user, url:user_session_path) do |f|
      %dl
        %dt= f.label :email
        %dd= f.email_field :email
        %dt= f.label :password
        %dd= f.password_field :password
      = f.submit 'ログインする'
   :javascript
     $('.header__login-button a').click(function(){
       $('.popup-login').css({ 'display' : 'block'});
     });
````

といった具合です。読出元のdashboard.html.hamlでは、
render_cellsメソッドを使うだけ。
コントローラーとviewを一緒くたに読みだしてくれます。

# Cells導入方法

gemfileに書いて

```ruby:Gemfiles
gem 'cells'
```

bundle installして

```コマンドライン
bundle instrall
```

generateします。

```コマンドライン
rails generate cell popup_login show -e haml
  create  app/cells/
  create  app/cells/popup_login
  create  app/cells/popup_login_cell.rb
  create  app/cells/popup_login/show.html.haml
  create  test/cells/popup_login_cell.rb
```

-e hamlでerbではなくhamlで書きだしてくれます。


cellsの部分テンプレートを読み出す場合は

```
= render_cell :popup_login, :show, :property => @property_name
# 上記は変数を受け渡す場合の例
```

といった感じです。


# 公式サイト

helper等より詳細な設定は下記をご参考ください。

github : apotonick/cells
https://github.com/apotonick/cells