Фильтр для выполнения до рендера, но после контроллера? - PullRequest
39 голосов
/ 14 февраля 2012

Предположим, у меня есть некоторая логика в базовом контроллере для передачи информации в представление для создания чего-то вроде хлебной крошки:

class ContextAwareController < ApplicationController

  after_filter :build_breadcrumb

  def build_breadcumb
    #...
  end
end

Я хочу, чтобы этот метод build_breadcrumb выполнял после основногологика контроллера, но за до представление визуализируется.

Приведенный выше код выполняется слишком поздно, но before_filter будет слишком рано.

Может кто-нибудь предложить способ выполнитьэто без явного вызова build_breadcumb в конце каждого из действий в дочерних контроллерах?

Спасибо

Ответы [ 5 ]

53 голосов
/ 18 сентября 2012

У меня была такая же проблема, и я решил ее так:

class ApplicationController < ActionController::Base
  def render *args
    add_breadcrumbs
    super
  end
end
2 голосов
/ 09 сентября 2014

Если мы переопределяем render, мы на самом деле вообще не используем цепочку фильтров, поэтому может быть проще определить, какое действие мы используем, используя @_action_name.

StuffController < ApplicationController

  def my_filter
    # Do the stuff
  end

  def render(*args)
    my_filter if @_action_name == "show"
    super
  end

end
2 голосов
/ 07 февраля 2013

Есть также несколько драгоценных камней для достижения этой цели.Одним из них является rails3_before_render .Он работает аналогично фильтрам, например:

class PostsController < ApplicationController
  before_render :ping, :except => [:destroy]

  def index; end
  def new; end
  def show; end
  def destroy; end                                                                          

  private
    def ping
      Rails.logger.info "Ping-Pong actions"
    end
end

(фрагмент кода скопирован из документации по гемам)

2 голосов
/ 14 февраля 2012

Я считаю, что рендеринг начинается при вызове рендера, и нет способа отложить его по умолчанию.Вот одна вещь, которую вы можете сделать: фильтры

применяются в том же порядке, в котором они были объявлены.Поэтому создайте второй после-фильтр, который вызывает метод render с аргументами массива, хранящимися в переменной класса.Затем в любом месте, где вы обычно вызываете render, установите переменную.

0 голосов
/ 05 сентября 2013

Вы можете сделать так, чтобы подделать before_render:

class StuffController < ApplicationController
  before_filter :my_filter, only: [:index, :show]

  def my_filter
    @my_filter = true
  end
  def _my_filter
    # Do the actual stuff here
  end
  def render(*args)
    _my_filter if @my_filter
    super
  end
end

Спасибо @ joshua-muheim за подсказку по использованию render

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...