Simple Rails Multi-Tenancy II

I suppose it’s about time I updated my [Simple Rails Multi-Tenancy](http://samuel.kadolph.com/2010/12/simple-rails-multi-tenancy/) post to use the latest rails [3.1.1](https://rubygems.org/gems/rails/versions/3.1.1). Not much has changed from the 3.0 beta to 3.1.1 in terms of the method I use to achieve multi-tenancy but the code has become a bit cleaner (but the patch required is a bit larger). This time around I’ll skip the commands and just go straight to the code itself.

#####[_app/models/tenant.rb_][app/models/tenant.rb]#####

class Tenant < ActiveRecord::Base class << self def current Thread.current[:tenant] end def current=(tenant) Thread.current[:tenant] = tenant end end validates :name, :host, presence: true def with previous, Tenant.current = Tenant.current, self yield ensure Tenant.current = previous end end #####[_app/models/tenant_scoped_model.rb_][app/models/tenant_scoped_model.rb]##### class TenantScopedModel < ActiveRecord::Base class << self def build_default_scope if method(:default_scope).owner != ActiveRecord::Base.singleton_class evaluate_default_scope { default_scope } elsif default_scopes.any? evaluate_default_scope do default_scopes.inject(relation) do |default_scope, scope| if scope.is_a?(Hash) default_scope.apply_finder_options(scope) elsif !scope.is_a?(ActiveRecord::Relation) && scope.respond_to?(:call) if scope.respond_to?(:arity) && scope.arity == 1 scope = scope.call(self) else scope = scope.call end default_scope.merge(scope) else default_scope.merge(scope) end end end end end end self.abstract_class = true belongs_to :tenant default_scope do |model| model.where(:tenant_id => Tenant.current)
end
end

#####[_app/controllers/application_controller.rb_][app/controllers/application_controller.rb]#####

class ApplicationController < ActionController::Base protect_from_forgery around_filter :with_tenant protected attr_reader :current_tenant def with_tenant @current_tenant = Tenant.find_by_host!(request.host) @current_tenant.with { yield } end end #####[_app/helpers/application_helper.rb_][app/helpers/application_helper.rb]##### module ApplicationHelper attr_reader :current_tenant end All of the migrations and the products model remain the same. Demo sites are still set up: [3][buraa] [that][wuxug] [exist][zovco] in the tenant table and [1 that does][nx] not. All code is [available in a github repository][github-repo]. [app/controllers/application_controller.rb]: https://github.com/samuelkadolph/simple-rails-multi-tenancy/blob/3af10b8be90003699eabc9a09b7e3d6c0ba6c3e0/app/controllers/application_controller.rb [app/helpers/application_helper.rb]: https://github.com/samuelkadolph/simple-rails-multi-tenancy/blob/3af10b8be90003699eabc9a09b7e3d6c0ba6c3e0/app/helpers/application_helper.rb [app/models/tenant.rb]: https://github.com/samuelkadolph/simple-rails-multi-tenancy/blob/3af10b8be90003699eabc9a09b7e3d6c0ba6c3e0/app/models/tenant.rb [app/models/tenant_scoped_model.rb]: https://github.com/samuelkadolph/simple-rails-multi-tenancy/blob/3af10b8be90003699eabc9a09b7e3d6c0ba6c3e0/app/models/tenant_scoped_model.rb [buraa]: http://buraa.simple-rails-multi-tenancy.samuel.kadolph.com [wuxug]: http://wuxug.simple-rails-multi-tenancy.samuel.kadolph.com [zovco]: http://zovco.simple-rails-multi-tenancy.samuel.kadolph.com [nx]: http://nx.simple-rails-multi-tenancy.samuel.kadolph.com [github-repo]: https://github.com/samuelkadolph/simple-rails-multi-tenancy

2 Replies to “Simple Rails Multi-Tenancy II”

  1. Hi Samuel – trying to implement your strategy on rails 3.2.1 and getting this stack trace when trying to list products:

    activerecord (3.2.1) lib/active_record/relation.rb:500:in with_default_scope'
    activerecord (3.2.1) lib/active_record/relation.rb:166:in
    exec_queries’
    activerecord (3.2.1) lib/active_record/relation.rb:159:in block in to_a'
    activerecord (3.2.1) lib/active_record/explain.rb:40:in
    logging_query_plan’
    activerecord (3.2.1) lib/active_record/relation.rb:158:in to_a'
    activerecord (3.2.1) lib/active_record/relation/finder_methods.rb:159:in
    all’
    activerecord (3.2.1) lib/active_record/querying.rb:5:in all'
    app/controllers/products_controller.rb:5:in
    index’

    You can recreate easily in your example code by upgrading the gem file (I am also using sqlite):
    gem ‘rails’, ‘3.2.1’

    group :assets do
    gem ‘sass-rails’, ‘~> 3.2.3’
    gem ‘coffee-rails’, ‘~> 3.2.1’
    gem ‘uglifier’, ‘>= 1.0.3’
    end

    Do you have any idea how to fix this?
    Many thanks

Leave a Reply

Your email address will not be published. Required fields are marked *