Rails:在多个控制器操作中设置公共实例变量

应该如何让几个不同的控制器动作设置一个公共实例变量,以便在模板 运行后 使用

换句话说,我希望这在我的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()都进行了分页,每个都使用参数@limit@limit (通过全局的before_filter )来查看数据切片。 大。 现在我想要一个通用方法来为“下一个切片”链接计算RESTful URL。 我被鼓励看到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)这样的事情,但我不确定它是否会起作用。 想一想,如果我要修改模板,那么我也可以设置一个应用程序帮助器。 我还不确定最好的解决方案是什么。

更新:接受的答案是“使用助手”。

感谢大家的更新。 我从中吸取了教训,就像全局变量一样,助手是有原因的,当它们明显有益和简洁时,不要被忽视。

首先,您不希望尝试在控制器操作和模板渲染之间插入代码。 为什么? 因为您希望控制器操作可以自由选择要提供的响应类型。 它可能只返回XML,JSON,头文件,重定向,什么都没有等等。这就是为什么在呈现响应后执行filter之后的原因。

其次,你不想修补补丁Fixnum 。 我的意思是,也许这样做,但我没有。 至少不是这样,除非我从中得到一些完全邪恶的语义好处,比如能说3.blind_mice 。 猴子修补它像这样的随机用例似乎是一个维护头痛的道路。

您提到将所有控制器的特定于案例的代码重构为前置filter并按顺序运行它们。 这让我想到了… @foo在每种情况下都是一样的吗? 如果是这种情况,那么在filter之前就可以正常工作:

 before_filter :do_common_stuff def do_common_stuff @foo = common_foo @bar = do_something_with @foo end 

这是一种完全合法的方法。 但是如果@foo从控制器变为控制器……那么,你还有一些选择。

您可以将之前的filter分成两半,并为每个控制器自定义一个。

 # 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 

但是你知道,如果这是一个简单的案例,不需要数据库访问或网络访问或类似的东西……你的情况不是……不要自杀。 不要流汗吧。 扔进帮手吧。 这就是他们所要求的,帮助。 你基本上只是将一些视图数据重新排列成一个稍微容易使用的forms。 帮助是我的投票。 你可以将它命名为next_url 。 🙂

我会在@foo上有一个返回条形的方法,这样你就可以在视图中使用@foo.bar

<% @bar = @foo.bar %> #如果你真的不想改变自己的观点,但是你没有听到我的意见:)

在模板中使用<%= do_some_calculations(@foo) %> 。 这是直截了当的方式。