Rails:基于子域范围查询的最佳实践? [英] Rails: best practice to scope queries based on subdomain?

查看:24
本文介绍了Rails:基于子域范围查询的最佳实践?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 Rails(当前为 2.3.4)应用程序,该应用程序利用子域来隔离独立的帐户站点.明确地说,我的意思是 foo.mysite.com 应该显示 foo 帐户的内容,而 bar.mysite.com 应该显示 bar 的内容.

I'm working on a Rails (currently 2.3.4) app that makes use of subdomains to isolate independent account sites. To be clear, what I mean is foo.mysite.com should show the foo account' content and bar.mysite.com should show bar's content.

确保所有模型查询都在当前子域范围内的最佳方法是什么?

What's the best way to ensure that all model queries are scoped to the current subdomain?

例如,我的一个控制器看起来像:

For example, one of my controllers looks something like:

@page = @global_organization.pages.find_by_id(params[:id])        

(注意 @global_organization 是通过 subdomain-fu 在 application_controller 中设置的.)当我更喜欢的是:

(Note @global_organization is set in the application_controller via subdomain-fu.) When what I would prefer is something like:

@page = Page.find_by_id(params[:id])

页面模型找到的位置会自动限定在正确的组织中.我试过使用这样的 default_scope 指令:(在页面模型中)

where the Page model finds are automatically scoped to the right organization. I've tried using the default_scope directive like this: (in the Page model)

class Page < ActiveRecord::Base
  default_scope :conditions => "organization_id = #{Thread.current[:organization]}"
  # yadda yadda
end

(再次强调,同样的 application_controller 将 Thread.current[:organization] 设置为组织的 id 以进行全局访问.)这种方法的问题是默认范围在第一次请求时设置,并且永远不会改变对不同子域的后续请求.

(Again, just to note, the same application_controller sets Thread.current[:organization] to the organization's id for global access.) The problem with this approach is that the default scope gets set on the first request and never changes on subsequent requests to different subdomains.

目前有三个明显的解决方案:

Three apparent solutions thus far:

1 为每个子域使用单独的虚拟主机,并为每个子域运行应用程序的不同实例(使用 mod_rails).对于此应用,这种方法不可扩展.

1 Use separate vhosts for each subdomain and just run different instances of the app per subdomain (using mod_rails). This approach isn't scalable for this app.

2 使用上面的原始控制器方法.不幸的是,应用程序中有相当多的模型,而且许多模型是从组织中删除的一些连接,因此这种表示法很快变得很麻烦.更糟糕的是,这主动要求开发人员记住并应用限制或冒重大安全问题的风险.

2 Use the original controller approach above. Unfortunately there are quite a number of models in the app and many of the models are a few joins removed from the organization, so this notation quickly becomes cumbersome. What's worse is that this actively requires developers to remember and apply the limitation or risk a significant security problem.

3 使用 before_filter 重置每个请求上模型的默认范围.不确定此处的性能影响或如何最好地选择每个请求更新哪些模型.

3 Use a before_filter to reset the default scope of the models on each request. Not sure about the performance hit here or how best to select which models to update per-reqeust.

想法?我还缺少其他任何解决方案吗?这似乎是一个足够普遍的问题,必须有一个最佳实践.感谢所有输入,谢谢!

Thoughts? Any other solutions I'm missing? This would seem to be a common enough problem that there's gotta be a best practice. All input appreciated, thanks!

推荐答案

您是否尝试过将 default_scope 定义为 lambda?每次使用范围时都会评估定义选项的 lambda 位.

Have you tried defining the default_scope a lambda? The lambda bit that defines the options get evaluated every time the scope is used.

class Page < ActiveRecord::Base
  default_scope lambda do 
   {:conditions => "organization_id = #{Thread.current[:organization]}"}
  end
  # yadda yadda
end

它本质上是在做你的第三个选择,通过与你的前过滤魔法协同工作.但它比这更激进一点,开始在 Page 模型上使用的每一个发现.

It's essentially doing your third option, by working in tandem with your before filter magic. But it's a little more aggressive than that, kicking in on every single find used on the Page model.

如果您希望所有模型都具有这种行为,您可以将 default_scope 添加到 ActiveRecord::Base 中,但是您提到了几个连接距离.因此,如果您采用这条路线,则必须覆盖这些模型中的默认范围以解决连接问题.

If you want this behaviour for all models you could add the default_scope to ActiveRecord::Base, but you mention a few being a couple of joins away. So if you go this route, you'll have to override the default scopes in those models to address the joins.

这篇关于Rails:基于子域范围查询的最佳实践?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆