Edited at

Rails4でbefore_renderの実装

More than 3 years have passed since last update.

※ 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 にまとめておいた.


参考