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
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
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.
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
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.
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])