应该如何让多个不同 Controller 的操作设置一个公共(public)实例变量在模板中使用,但在操作运行之后。
换句话说,我希望它能在我的 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()
。 将所有 Controller 的特定于案例的代码重构为
case_specific_code()
并强制它们按顺序运行:before_filter :case_specific_code, :set_something_common
子类
application_controller
并重新定义index
方法。
有什么想法吗?谢谢。
编辑:马修的回应促使我澄清:
几个controller的index()都做了分页,每个都带参数@offset
和@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)
的操作,但我不确定它是否有效。想一想,如果我要修改模板,那么我不妨设置一个应用程序助手。我仍然不确定最好的解决方案是什么。
更新:接受的答案是“使用助手。”
感谢大家的更新。我学到的教训是,助手就像全局变量一样,存在是有原因的,当它们明显有益且简洁时,不应回避它们。
最佳答案
首先,您不想尝试在 Controller 操作和模板渲染“之间”插入代码。为什么?因为您希望 Controller 操作能够自由选择给出何种响应。它可以返回 XML、JSON、仅返回 header 、重定向、不返回任何内容等。这就是在渲染响应后执行 After 过滤器的原因。
其次,您不想对 Fixnum
进行猴子补丁。我的意思是,也许你会,但我不会。至少不经常,除非我从中获得一些完全邪恶的语义好处,比如能够说3.blind_mice
。猴子为像这样的随机用例修补它似乎是一个令人头疼的维护问题。
您提到将所有 Controller 的特定于案例的代码重构为 before 过滤器并按顺序运行它们。这让我想到...... @foo
在每种情况下都是相同的?如果是这种情况,那么过滤器之前的一个就可以正常工作:
before_filter :do_common_stuff
def do_common_stuff
@foo = common_foo
@bar = do_something_with @foo
end
这是一个完全合法的方法。但是如果 @foo 从一个 Controller 更改为另一个 Controller ......那么,您还有更多选择。
您可以将之前的过滤器分成两半,并为每个 Controller 自定义一个过滤器。
# 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
但是你知道,如果这是一个简单的案例,不需要数据库访问或网络访问或类似的东西......而你的案例不需要......不要自杀。别担心。把它扔进助手里。这就是他们在那里提供帮助的目的。基本上,您只是将一些 View 数据重新排列成稍微易于使用的形式。 helper 是我的一票。您可以将其命名为 next_url
。 :)
关于ruby-on-rails - rails : Set a common or global instance variable across several controller actions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/914226/