我正在开发一个Rails(目前是2.3.4)应用程序,该应用程序利用子域来隔离独立的帐户站点.要明确的是,我的意思是foo.mysite.com应该显示foo帐户的内容,bar.mysite.com应该显示栏的内容.
确保所有模型查询都限定在当前子域的最佳方法是什么?
例如,我的一个控制器看起来像:
@page = @global_organization.pages.find_by_id(params[:id])
Run Code Online (Sandbox Code Playgroud)
(注意@global_organization是通过subdomain-fu在application_controller中设置的.)当我喜欢的是:
@page = Page.find_by_id(params[:id])
Run Code Online (Sandbox Code Playgroud)
Page模型找到的位置自动限定在正确的组织中.我尝试过使用default_scope指令,如下所示:(在Page模型中)
class Page < ActiveRecord::Base
default_scope :conditions => "organization_id = #{Thread.current[:organization]}"
# yadda yadda
end
Run Code Online (Sandbox Code Playgroud)
(再次,请注意,相同的application_controller将Thread.current [:organization]设置为组织的全局访问ID.)此方法的问题是默认范围在第一个请求上设置,并且永远不会在后续请求中更改不同的子域名.
到目前为止有三种明显的解
1为每个子域使用单独的vhost,并且每个子域只运行应用程序的不同实例(使用mod_rails).此方法不适用于此应用.
2使用上面的原始控制器方法.不幸的是,应用程序中有相当多的模型,许多模型都是从组织中删除的一些连接,因此这种表示法很快变得很麻烦.更糟糕的是,这主动要求开发人员记住并应用限制或冒重大安全问题.
3使用before_filter重置每个请求的模型的默认范围.不确定此处的性能或如何最好地选择要更新的模型.
思考?我还缺少其他任何解决方案吗?这似乎是一个普遍的问题,必须有一个最佳实践.感谢所有投入,谢谢!
您是否尝试过定义default_scopea lambda?lambda每次使用范围时都会评估定义选项的位。
class Page < ActiveRecord::Base
default_scope lambda do
{:conditions => "organization_id = #{Thread.current[:organization]}"}
end
# yadda yadda
end
Run Code Online (Sandbox Code Playgroud)
它本质上是在做你的第三个选择,通过与你的过滤器魔法协同工作。但它比这更激进一点,会启动 Page 模型上使用的每一个发现。
如果您希望所有模型都具有这种行为,您可以将 default_scope 添加到 ActiveRecord::Base,但您提到了一些模型需要几个连接。因此,如果您采用此路线,则必须覆盖这些模型中的默认范围才能解决连接问题。
| 归档时间: |
|
| 查看次数: |
2862 次 |
| 最近记录: |