Rails: установить общую переменную экземпляра для нескольких действий контроллера - PullRequest
16 голосов
/ 27 мая 2009

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

Другими словами, я хочу, чтобы это работало в моем application_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.

Есть мысли? Спасибо.

Редактировать: ответ Мэтью побудил меня уточнить:

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

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

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

Ответы [ 3 ]

23 голосов
/ 29 мая 2009

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

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

Вы упоминаете о рефакторинге кода каждого конкретного контроллера в фильтр before и последующем их запуске. Что на мой взгляд ... @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. :)

4 голосов
/ 31 мая 2009

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

4 голосов
/ 27 мая 2009

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

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

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