LoginSignup
56
52

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-09-16

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

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

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

Cellsの利用シーンの具体例

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

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

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

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

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

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

_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コントローラに書いた場合(やらない方がいい例)

愚直に考えると…

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のコード。

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

がありましたが、

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

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

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

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

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に書いて

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

56
52
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
52