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)
из шаблона, но я не уверен, что он сработает. Подумайте об этом, если я собираюсь изменить шаблоны, я также могу настроить помощник приложения. Я все еще не уверен, какое лучшее решение.
Обновление: принятый ответ - "использовать помощника".
Спасибо за обновления от всех. Я выучил свой урок, что помощники, такие как глобальные переменные, существуют по какой-то причине и не должны избегать, когда они явно полезны и лаконичны.
Ответы
Ответ 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) %>
внутри ваших шаблонов.
Это прямой путь.