diff --git a/README.md b/README.md index d37f0b5..7d5a616 100644 --- a/README.md +++ b/README.md @@ -210,6 +210,28 @@ You can also explicitly specifiy a primary_key for AaT to use should the key dif acts_as_tenant(:account, :primary_key => 'primaryID') # by default AaT expects id ``` + +### Has and belongs to many ### + +You can scope a model that is part of a HABTM relationship by using the `through` option. + +```ruby +class Organisation < ActiveRecord::Base + has_many :organisations_users + has_many :users, through: :organisations_users +end + +class User < ActiveRecord::Base + has_many :organisations_users + acts_as_tenant :organisation, through: :organisations_users +end + +class OrganisationsUser < ActiveRecord::Base + belongs_to :user + acts_as_tenant :organisation +end +``` + Configuration options --------------------- An initializer can be created to control (currently one) option in ActsAsTenant. Defaults diff --git a/lib/acts_as_tenant/model_extensions.rb b/lib/acts_as_tenant/model_extensions.rb index d0603f9..dd5211d 100644 --- a/lib/acts_as_tenant/model_extensions.rb +++ b/lib/acts_as_tenant/model_extensions.rb @@ -24,9 +24,15 @@ def acts_as_tenant(tenant = :account, **options) keys = [ActsAsTenant.current_tenant.send(pkey)].compact keys.push(nil) if options[:has_global_records] - query_criteria = {fkey.to_sym => keys} - query_criteria[polymorphic_type.to_sym] = ActsAsTenant.current_tenant.class.to_s if options[:polymorphic] - where(query_criteria) + if options[:through] + query_criteria = {options[:through] => {fkey.to_sym => keys}} + query_criteria[polymorphic_type.to_sym] = ActsAsTenant.current_tenant.class.to_s if options[:polymorphic] + joins(options[:through]).where(query_criteria) + else + query_criteria = {fkey.to_sym => keys} + query_criteria[polymorphic_type.to_sym] = ActsAsTenant.current_tenant.class.to_s if options[:polymorphic] + where(query_criteria) + end else all end diff --git a/spec/dummy/app/models/account.rb b/spec/dummy/app/models/account.rb index 75ed86c..6e11e19 100644 --- a/spec/dummy/app/models/account.rb +++ b/spec/dummy/app/models/account.rb @@ -1,4 +1,6 @@ class Account < ActiveRecord::Base has_many :projects has_many :global_projects + has_many :users_accounts + has_many :users, through: :users_accounts end diff --git a/spec/dummy/app/models/user.rb b/spec/dummy/app/models/user.rb new file mode 100644 index 0000000..b1a3379 --- /dev/null +++ b/spec/dummy/app/models/user.rb @@ -0,0 +1,6 @@ +class User < ActiveRecord::Base + has_many :users_accounts + has_many :accounts, through: :users_accounts + + acts_as_tenant :account, through: :users_accounts +end diff --git a/spec/dummy/app/models/users_account.rb b/spec/dummy/app/models/users_account.rb new file mode 100644 index 0000000..aa59bde --- /dev/null +++ b/spec/dummy/app/models/users_account.rb @@ -0,0 +1,4 @@ +class UsersAccount < ActiveRecord::Base + acts_as_tenant :account + belongs_to :user +end diff --git a/spec/dummy/db/schema.rb b/spec/dummy/db/schema.rb index ec13a95..d68caa9 100644 --- a/spec/dummy/db/schema.rb +++ b/spec/dummy/db/schema.rb @@ -81,4 +81,14 @@ t.column :polymorphic_tenant_commentable_type, :string t.column :account_id, :integer end + + create_table :users, force: true do |t| + t.column :name, :string + end + + create_table :users_accounts, force: true do |t| + t.column :user_id, :integer + t.column :account_id, :integer + t.index [:user_id, :account_id], name: :index_users_accounts_on_user_id_and_account_id, unique: true + end end diff --git a/spec/fixtures/accounts.yml b/spec/fixtures/accounts.yml index b9f93a5..d2704e7 100644 --- a/spec/fixtures/accounts.yml +++ b/spec/fixtures/accounts.yml @@ -8,3 +8,11 @@ with_domain: name: domain subdomain: domain domain: domain.com + +abc: + name: abc + users: john, bob # habtm relation + +def: + name: def + users: john, alice # habtm relation \ No newline at end of file diff --git a/spec/fixtures/users.yml b/spec/fixtures/users.yml new file mode 100644 index 0000000..3caa9ed --- /dev/null +++ b/spec/fixtures/users.yml @@ -0,0 +1,8 @@ +john: + name: john + +bob: + name: bob + +alice: + name: alice \ No newline at end of file diff --git a/spec/models/model_extensions_spec.rb b/spec/models/model_extensions_spec.rb index 74d0529..3bfd56a 100644 --- a/spec/models/model_extensions_spec.rb +++ b/spec/models/model_extensions_spec.rb @@ -104,6 +104,25 @@ end end + describe "acts_as_tenant :through" do + let(:account) { accounts(:abc) } + + it "should scope User.all to the current tenant if set" do + ActsAsTenant.current_tenant = account + expect(User.count).to eq(account.users.count) + expect(User.all).to eq(account.users) + end + + it "should return all users when no current tenant is set" do + expect(User.count).to eq(3) + end + + it "should allow unscoping" do + ActsAsTenant.current_tenant = account + expect(User.unscoped.count).to be > account.users.count + end + end + describe "A tenant model with global records" do before do ActsAsTenant.current_tenant = account