ruby-on-rails - rails : Set a common or global instance variable across several controller actions

标签 ruby-on-rails model-view-controller filter

应该如何让多个不同 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/

相关文章:

ruby-on-rails - Rails DB 中的 CamelCase 而不是 snake_case

ruby-on-rails - 设计在身份验证失败时使用 JSON 请求登录不起作用

php - 如何使用 PHP 允许 HTML 进入白名单

php - Symfony2 : Echoing JSON From a Controller for Use in an ExtJS 4 Grid

asp.net-mvc - MVVM 模式的核心是什么?

ios - 以灰度绘制 UIView?

javascript - ExtJS Store 动态过滤已过滤的商店

mysql - rails : Can I exclude entries from all queries?

ruby-on-rails - Bundler 找不到 gem "bundler": 的兼容版本

c# - 我想获取单个数据库 SQL 字符串