为什么我的线程变量在Rails中是间歇性的?

时间:2010-11-18 17:49:50

标签: ruby-on-rails ruby

我的应用程序控制器中有以下内容:

before_filter :set_current_subdomain

  protected
    def set_current_subdomain
      Thread.current[:current_subdomain] = current_subdomain
      @account = Account.find_by_subdomain(current_subdomain)
    end

    def current_subdomain
      request.subdomain
    end

然后在我的一些模型中使用以下内容:

default_scope :conditions => { :account_id => (Thread.current[:account].id unless Thread.current[:account].nil?) }  

现在,这有效 - 有些时候。我举例说明了加载索引方法并获取应用作用域的记录列表,但有时候得到一个空列表,因为Thread.current [:account_id]的结果为nil,即使请求中较早的查询正在运行使用相同的值。

问题是,为什么这不起作用,是否有更好的方法来设置当前请求的全局变量?

1 个答案:

答案 0 :(得分:5)

操纵Thread局部变量是一个非常糟糕的主意,除了悲伤,心痛和痛苦之外别无他法。不能保证请求处理的不同部分将由同一个线程处理,因此,您的变量可能最终会丢失。

Rails约定是在ApplicationController的上下文中创建实例变量。简单来说,你真正做的就是:

class ApplicationController < ActionController::Base
  before_filter :set_current_subdomain

  attr_reader :current_subdomain
  helper_method :current_subdomain

protected
  def set_current_subdomain
    @current_subdomain = request.subdomain

    @account = Account.find_by_subdomain(@current_subdomain)
  end
end

您创建的任何@...类型变量都将附加到与当前请求关联的ApplicationController实例。重要的是要注意每个请求将被发布一个适当的控制器类的全新实例。

你可以自由地创建你想要的任何实例变量,只要它们不会与Rails本身使用的那些冲突,但一般而言,这种情况不常发生,而且通常会在方法名称上发生冲突。

类级别实例变量将在启用“缓存类”标志的环境中的请求之间保持不变。在开发环境中,每次发出请求时都会重新加载控制器类,以确保它反映源文件的当前状态。