【问题标题】:Why do my controller's instance variables not work in views (Rails)为什么我的控制器的实例变量在视图中不起作用(Rails)
【发布时间】:2026-01-05 00:30:01
【问题描述】:

我想向我的控制器添加几个实例变量,因为有问题的变量需要从多个操作的视图中获取。然而,下面的例子并没有像我预期的那样工作。

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 从控制器中获取实例变量并使其在视图中可用。如果我在操作方法中分配相同的变量,它工作正常 - 但我不想做两次。为什么我的方法行不通?

(注意:这是一个有点垃圾的例子,但我希望它有意义)

编辑:我在这里找到了这个问题的答案:When do Ruby instance variables get set?

编辑 2:什么时候是使用过滤器(例如 before_filter 和 initialize 方法)的最佳时间?

【问题讨论】:

    标签: ruby-on-rails ruby scope instance-variables


    【解决方案1】:

    这些类型的事情应该在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 ]
    

    希望这会有所帮助。

    编辑:这里有更多关于filters in ActionController的信息。

    【讨论】:

    • 是的,谢谢。但是,在发布此消息后不久,我找到了另一个答案(我更新了问题以反映这一点)。何时是使用 before_filter 和/或初始化的最佳时间?
    • 我会说你应该使用 before_filter 如果它是任何类型的设置工作必须处理多个动作。
    • 作为我刚刚留下的评论的示例,在验证某人是否已登录时,您通常可能在ApplicationController 中有一个方法,并将before_filter 应用于任何需要用户登录的操作登录。在需要有人登录的每个操作中都使用该代码是没有意义的。
    • 了解 - 如果需要,这将更容易拆分为多个过滤方法,和/或在必要时分配给特定操作。谢谢 - 当你来自类 C 语言时,这有点 Ruby 陷阱。
    • 为了更好的组织和可读性,最好使用 before_filter。
    【解决方案2】:

    那些不是实例变量,是吗?

    class A
      @x = 5
      def f
        puts @x
      end
    end
    
    A.new.f
    => nil
    

    您是在类级别而不是实例级别定义它。正如“theIV”所指出的,您需要在实例方法中分配它们。

    【讨论】:

    • 我误以为你可以像在 c# 或 Java 等语言中那样这样做:class ExampleController { private string var1 = "cheese"; // ... }
    • 在Java中,你声明了一个实例变量;在 Ruby 中,你的变量没有被声明,所以没有真正的等价物。 Ruby "class".."end" 中的任何内容基本上都会被评估,因此将其视为等效于 Java 静态初始化程序可能会有所帮助。
    最近更新 更多