LoginSignup
8

More than 5 years have passed since last update.

Rails4でbefore_renderの実装

Last updated at Posted at 2016-01-27

※ RubyやRailsの素人なので,用語や表現など間違っているところがあったら,指摘してもらえば幸いです!

はじめに

コントローラで,あるアクションを処理してから,ビューがレンダーされる前の間に,何かの処理を挟み込む場合ができて,色々考えたり調べたりして方法をまとめてみた.

内容

アプローチ1

ActionController::Instrumentation#renderをオバーライドする.

class UsersController < ApplicationController
  def render(*args, &block)
    foo if action_name == "index"
    bar if action_name == "show"

    super
  end
end

でも,Reusabilityがまったくないコードになってしまった…

アプローチ2

before_actionafter_actionのように,before_renderというフックメソッドとして実装する.
コントローラのコンサーンとして書いて,複数のコントローラで使えるようにする.

app/controllers/concerns/before_render.rb
module BeforeRender
  extend ActiveSupport::Concern

  included do
    define_callbacks :render
    alias_method_chain :render, :before_render
  end

  def render_with_before_render(*options, &block)
    run_callbacks(:render) do
      render_without_before_render(*options, &block)
    end
  end

  module ClassMethods
    def before_render(*names, &block)
      _insert_callbacks(names, block) do |name, options|
        set_callback(:render, :before, name, options)
      end
    end
  end
end

コントローラでは,こんな風に使える.

app/controllers/users_controller.rb
class UsersController < ApplicationController
  include BeforeRender

  before_render :foo, only: [:show]
  before_render unless: [:destroy] do |controller|
    bar
  end

  def foo
  end

  def bar
  end
end

まとめ

ちゃんとできているのか確信はないけど,一通りテストをやってみた結果,思い通りには動いてる.
コードは,http://github.com/cryeo/before_render にまとめておいた.

参考

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
8