Почему переменные экземпляра моего контроллера не работают в представлениях (Rails)

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

class ExampleController < ApplicationController
  @var1 = "Cheese"
  @var2 = "Tomato"

  def show_pizza_topping
    # What I want is the above instance vars from within the view here
  end

  def show_sandwich_filling
    # What I want is the above instance vars from within the view here
  end
end

Насколько я понимаю, Rails берет переменные экземпляра из контроллера и делает их доступными в представлении. Если я назначаю одни и те же переменные в методах действий, все работает нормально, но я не хочу делать это дважды. Почему мой способ не работает?

(Примечание: это немного бессмысленный пример, но я надеюсь, что он имеет смысл)

РЕДАКТИРОВАТЬ: я нашел ответ на этот вопрос здесь: Когда переменные экземпляра Ruby получают установить?

РЕДАКТИРОВАТЬ 2: когда лучше всего использовать фильтры, такие как before_filter и метод инициализации?


person Mark Embling    schedule 11.09.2009    source источник


Ответы (2)


Эти типы вещей должны обрабатываться в before_filter. Фильтр перед, как следует из названия, — это метод, который будет вызываться перед любыми действиями или только перед теми, которые вы объявили. Пример:

class ExampleController < ApplicationController

  before_filter :set_toppings

  def show_pizza_topping
    # What I want is the above instance vars from within the view here
  end

  def show_sandwich_filling
    # What I want is the above instance vars from within the view here
  end

protected

  def set_toppings
    @var1 = "Cheese"
    @var2 = "Tomato"
  end

end

Или вы можете сделать так, чтобы ваш before_filter работал только с одним из ваших действий.

before_filter :set_toppings, :only => [ :show_pizza_topping ]

Надеюсь это поможет.

РЕДАКТИРОВАТЬ: вот еще немного информации о фильтрах в ActionController< /а>.

person theIV    schedule 11.09.2009
comment
Да, это так, спасибо. Однако вскоре после публикации я нашел другой ответ (я обновил вопрос, чтобы отразить это). Когда лучше всего использовать before_filter и/или инициализацию? - person Mark Embling; 11.09.2009
comment
Я бы сказал, что вы должны использовать before_filter, если это какая-либо работа по настройке, которая должна работать с несколькими действиями. - person theIV; 11.09.2009
comment
В качестве примера комментария, который я только что оставил, при проверке того, что кто-то вошел в систему, вы обычно можете иметь метод в ApplicationController и применять before_filter к любому действию, которое требует, чтобы пользователь вошел в систему. Было бы бессмысленно иметь этот код в каждом действии, которое требует, чтобы кто-то вошел в систему. - person theIV; 11.09.2009
comment
Понятно - это облегчило бы разделение на несколько методов фильтрации, если это необходимо, и/или выделение определенных действий, если это необходимо. Спасибо - это немного похоже на Ruby, когда вы пришли из C-подобных языков. - person Mark Embling; 11.09.2009
comment
Для лучшей организации и удобочитаемости лучше использовать before_filter. - person Vizjerai; 11.09.2009

Это не переменные экземпляра, не так ли?

class A
  @x = 5
  def f
    puts @x
  end
end

A.new.f
=> nil

Вы определяете его на уровне класса, а не на уровне экземпляра. Как указывает «theIV», вам нужно назначить их внутри метода экземпляра.

person Ken    schedule 11.09.2009
comment
У меня сложилось ошибочное впечатление, что вы можете сделать это таким же образом, как в таких языках, как C# или Java: class ExampleController { private string var1 = cheese; // ... } - person Mark Embling; 11.09.2009
comment
В Java вы объявляете переменную экземпляра; в Ruby ваши переменные не объявляются, поэтому реального эквивалента нет. Все, что находится внутри класса Ruby class..end, в основном вычисляется, так что это может помочь думать об этом как об эквиваленте статического инициализатора Java. - person Ken; 11.09.2009