我的应用程序控制器中有以下内容:
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,即使请求中较早的查询正在运行使用相同的值。
问题是,为什么这不起作用,是否有更好的方法来设置当前请求的全局变量?
答案 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本身使用的那些冲突,但一般而言,这种情况不常发生,而且通常会在方法名称上发生冲突。
类级别实例变量将在启用“缓存类”标志的环境中的请求之间保持不变。在开发环境中,每次发出请求时都会重新加载控制器类,以确保它反映源文件的当前状态。