Rails ApplicationController 和 app/helpers 中的助手之间不共享实例变量

Rails instance variables not shared between helpers in ApplicationController and app/helpers

我在控制器中设置了一个实例变量。

@cost=[1,2,3]

最终调用了一个视图,该视图调用了一个部分,而该部分又在 app/helpers 中调用了一个助手。

在调试器中,当我进入该辅助方法时,我可以看到 @cost 仍然是 [1,2,3]。

在辅助方法中,我将@cost 设置为 [4,5,6],然后调用在 application_controller.rb.

中定义的辅助方法 set_cost
class ApplicationController < ActionController::Base
  helper_method :set_cost
  def set_cost
    @cost=[7,8,9]
  end
end

当我输入 set_cost 时,我可以在调试器中看到 @cost 已恢复为 [1,2,3]。

当我 return 回到 app/helpers 中的辅助方法时,我可以在调试器中看到 @cost 不再是 [7,8,9],而是恢复为 [4 ,5,6].

如果我直接从控制器调用 set_cost,当控制 return 回到控制器时,@cost 是 [7,8,9]。

有没有一种方法可以跨 app/helpers 中的控制器、视图、部分、辅助方法和 application_controller.rb 中的辅助方法访问和操作实例变量,以便引用/值保持一致?就好像它正在改变范围并制作变量的本地版本。

我意识到将 @cost 传递给 set_cost(我的实际功能比我展示的更复杂)、更新它,然后 return 将它传递给 set_cost 可能有设计和实际好处那里的原始赋值函数,但即使它完成了我想要的,我也想更好地理解 Rails 设计。我认为实例变量类似于全局变量,但显然不是。

感谢您的帮助。

实例变量不是全局变量 - 它与特定实例相关联(因此得名)。

Rails 允许您从视图访问控制器实例变量。这通过复制控制器实例变量来实现:AbstractController::Rendering creates a hash of all the instance variables. Later on, the view object uses that hash to recreate 实例变量中的 view_assigns 方法。当你说好像有正在制作的变量的本地副本时,这几乎就是正在发生的事情。

值是共享的,即最初在视图和控制器中 @cost.object_id 是相同的。如果您的助手要执行 @cost.replace(...) 之类的操作,那么您会在任何地方看到该更改,但是当您重新分配 @cost 时,该分配不会影响控制器(反之亦然 - 控制器实例变量的副本到该视图是一次性操作)。

"Normal" 助手最终成为视图上下文的实例方法,但是 helper_method 创建的是控制器实例方法 - rails 基本上定义了一个看起来像

def set_cost
  controller.set_cost
end

您可以通过改变 @cost 而不是重新分配它来避免这些问题,但我发现视图助手可能像这样改变状态的想法令人惊讶。