Help us understand the problem. What is going on with this article?

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

参考

cryeo
東大院情理工石川渡辺研M1
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away