Rails: best practice to scope queries based on subdomain?

后端 未结 5 1480
傲寒
傲寒 2020-12-24 04:17

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 f

相关标签:
5条回答
  • 2020-12-24 04:17

    I've found the acts_as_tenant gem [github] works great for this feature. It does the scoping for you with minimal extra effort, and also makes bypassing the scoping difficult.

    Here's the initial blog post about it: http://www.rollcallapp.com/blog/2011/10/03/adding-multi-tenancy-to-your-rails-app-acts-as-tenant

    0 讨论(0)
  • 2020-12-24 04:20

    We've been using https://github.com/penguincoder/acts_as_restricted_subdomain for the last 2 years, but it only works with Rails 2.3.

    We are currently trying to upgrade (and gemmify) the plugin to work with Rails 3. I'm curious on how you worked your problem out.

    0 讨论(0)
  • 2020-12-24 04:20

    You might be better of having a database per account and switching the database connection based on the subdomain.

    In addition to the above link if you have a model (in your case Account) that you want to use the default database just include establish connection in the model.

    class Account < ActiveRecord::Base
    
      # Always use shared database
      establish_connection  "shared_#{RAILS_ENV}".to_sym
    
    0 讨论(0)
  • 2020-12-24 04:31

    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
    

    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.

    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.

    0 讨论(0)
  • 2020-12-24 04:39

    Be careful going with default scope here, as it will lead you into a false sense of security, particularly when creating records.

    I've always used your first example to keep this clear:

    @page = @go.pages.find(params[:id])
    

    The biggest reason is because you also want to ensure this association is applied to new records, so your new/create actions will look like the following, ensuring that they are properly scoped to the parent association:

    # New
    @page = @go.pages.new
    
    # Create
    @page = @go.pages.create(params[:page])
    
    0 讨论(0)
提交回复
热议问题