Подтвердить что ты не робот

Rails: установка общей переменной экземпляра для нескольких действий контроллера

Как следует иметь несколько действий с несколькими контроллерами, установить общую переменную экземпляра для использования в шаблонах, но после запуска действия.

Другими словами, я хочу, чтобы это работало в моем приложении_controller.

class ApplicationController < ActionController::Base
  after_filter :set_something_common

  def set_something_common
    # All controllers' actions have queried the DB and set @foo for me...
    @bar = some_calculation_on(@foo)
    # ... and all templates expect @bar to bet set.
  end
end

Этот не работает, потому что after_filter запускается после рендеринга. Хорошо. Но каков правильный шаблон?

Опять же, важно, чтобы set_something_common запускалось после действия, потому что эти действия делали конкретные вещи; но все они устанавливают @foo.

Ни одна из моих идей не кажется идеальной:

  • Вызовите set_something_common() в нижней части каждого действия, которое ему нужно.
  • Рефакторинг кода конкретного контроллера в case_specific_code() и заставить их работать в порядке:

    before_filter :case_specific_code, :set_something_common
    
  • Подкласс application_controller и переопределите метод index.

Любые мысли? Спасибо.

Изменить: ответ Мэтью заставил меня уточнить:

Несколько индексов указателей() все делают разбиение на страницы, каждый из которых принимает параметры @offset и @limit (через глобальный before_filter) для просмотра срезов данных. Отлично. Теперь мне нужен общий метод для вычисления URL-адреса RESTful для ссылки "Следующий фрагмент". Мне было приятно видеть, что url_for() генерирует URL-адрес, возвращающийся к тому же ресурсу, поэтому я попытался:

def set_something_common # really called set_next_url, truth be told
  @next_url = url_for(:offset => @offset + @limit, :limit => @limit)
end

Я попытаюсь исправить FIXNUM, так что я могу сделать что-то вроде @offset.next_url_for(self, @limit) из шаблона, но я не уверен, что он сработает. Подумайте об этом, если я собираюсь изменить шаблоны, я также могу настроить помощник приложения. Я все еще не уверен, какое лучшее решение.

Обновление: принятый ответ - "использовать помощника".

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

4b9b3361

Ответ 1

Во-первых, вы не хотите пытаться вставлять код "между" действием контроллера и рендерингом шаблона. Зачем? Потому что вы хотите, чтобы действие контроллера имело свободу выбора того, какой ответ дать. Он может возвращать XML, JSON, только заголовки, перенаправление, ничего и т.д. Поэтому после того, как фильтры выполняются после того, как ответ был обработан.

Во-вторых, вы не хотите патча обезьяны Fixnum. Я имею в виду, может быть, так и есть, но я этого не делаю. Не часто, по крайней мере, и нет, если я не получу от него совершенно злобные семантические выгоды, например, возможность сказать 3.blind_mice. Обезьяна, исправляющая его для случайного использования, похожего на эту проблему, кажется головной болью обслуживания в будущем.

Вы упомянули рефакторинг всего кода конкретного случая контроллера в фильтр перед запуском и его последовательный запуск. Что мне кажется... @foo - то же самое в каждом случае? Если это случай, то один до фильтра будет работать нормально:

before_filter :do_common_stuff
def do_common_stuff
  @foo = common_foo
  @bar = do_something_with @foo
end

Это абсолютно законный подход. Но если @foo меняется с контроллера на контроллер... ну, у вас есть еще несколько вариантов.

Вы можете отделить свои фильтры до двух половинок и настроить один на контроллер.

# application_controller:
before_filter :get_foo, :do_something_common
def do_something_common
  @bar = do_something_with @foo
end

# baz_controller:
def get_foo
  @foo = pull_from_mouth
end

#baf_controller:
def get_foo
  @foo = pull_from_ear
end

Но вы знаете, если это простой случай, который не нуждается в доступе к базе данных или доступе к сети или что-то в этом роде... в вашем случае нет... не убивайте себя. И не потейте. Брось его в помощника. Для чего они нужны, чтобы помочь. Вы в основном просто переставляете некоторые данные вида в форму, которая немного проще в использовании. Помощник - мой голос. И вы можете просто назвать его next_url.:)

Ответ 2

У меня был бы метод на @foo, который возвращает панель, таким образом вы можете использовать @foo.bar в своих представлениях.

<% @bar = @foo.bar %> #если вы действительно не хотите менять свои взгляды, но вы этого не слышали:)

Ответ 3

Используйте <%= do_some_calculations(@foo) %> внутри ваших шаблонов. Это прямой путь.