LoginSignup
8

More than 5 years have passed since last update.

posted at

updated at

Rails4でbefore_renderの実装

※ 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
What you can do with signing up
8