From d54d8f6be1f7a526f28a6ca0cca2248761f6bbc7 Mon Sep 17 00:00:00 2001 From: Kevin Southworth Date: Sun, 1 Sep 2019 08:24:25 -0400 Subject: [PATCH] allow changing tenant on models using new without_tenant! block --- lib/acts_as_tenant/model_extensions.rb | 21 +++++++++++-- spec/acts_as_tenant/model_extensions_spec.rb | 33 ++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/acts_as_tenant/model_extensions.rb b/lib/acts_as_tenant/model_extensions.rb index 1a882a1..2697562 100644 --- a/lib/acts_as_tenant/model_extensions.rb +++ b/lib/acts_as_tenant/model_extensions.rb @@ -1,6 +1,7 @@ module ActsAsTenant @@tenant_klass = nil @@models_with_global_records = [] + @@mutable_tenant = false def self.set_tenant_klass(klass) @@tenant_klass = klass @@ -50,6 +51,14 @@ def self.unscoped? !!unscoped end + def self.mutable_tenant!(toggle) + @@mutable_tenant = toggle + end + + def self.mutable_tenant? + @@mutable_tenant === true + end + class << self attr_accessor :test_tenant @@ -94,6 +103,13 @@ def self.without_tenant(&block) self.unscoped = old_unscoped end + def self.without_tenant!(&block) + ActsAsTenant.mutable_tenant!(true) + self.without_tenant(&block) + ensure + ActsAsTenant.mutable_tenant!(false) + end + module ModelExtensions def self.included(base) base.extend(ClassMethods) @@ -102,6 +118,7 @@ def self.included(base) module ClassMethods def acts_as_tenant(tenant = :account, options = {}) ActsAsTenant.set_tenant_klass(tenant) + ActsAsTenant.mutable_tenant!(false) ActsAsTenant.add_global_record_model(self) if options[:has_global_records] @@ -168,13 +185,13 @@ def acts_as_tenant(tenant = :account, options = {}) to_include = Module.new do define_method "#{fkey}=" do |integer| write_attribute("#{fkey}", integer) - raise ActsAsTenant::Errors::TenantIsImmutable if send("#{fkey}_changed?") && persisted? && !send("#{fkey}_was").nil? + raise ActsAsTenant::Errors::TenantIsImmutable if send("#{fkey}_changed?") && persisted? && !send("#{fkey}_was").nil? && !ActsAsTenant.mutable_tenant? integer end define_method "#{ActsAsTenant.tenant_klass.to_s}=" do |model| super(model) - raise ActsAsTenant::Errors::TenantIsImmutable if send("#{fkey}_changed?") && persisted? && !send("#{fkey}_was").nil? + raise ActsAsTenant::Errors::TenantIsImmutable if send("#{fkey}_changed?") && persisted? && !send("#{fkey}_was").nil? && !ActsAsTenant.mutable_tenant? model end diff --git a/spec/acts_as_tenant/model_extensions_spec.rb b/spec/acts_as_tenant/model_extensions_spec.rb index 8469c70..8c47177 100644 --- a/spec/acts_as_tenant/model_extensions_spec.rb +++ b/spec/acts_as_tenant/model_extensions_spec.rb @@ -394,6 +394,39 @@ end end + describe "::without_tenant!" do + it "should return the value of the block" do + value = ActsAsTenant.without_tenant! do + "something" + end + expect(value).to eq "something" + end + + it "should raise an error when no block is provided" do + expect { ActsAsTenant.without_tenant! }.to raise_error(ArgumentError, /block required/) + end + + it "should set tenant back to immutable after the block" do + ActsAsTenant.without_tenant! do + "something" + end + expect(ActsAsTenant.mutable_tenant?).to eq false + end + + describe 'mutability' do + before do + @account = Account.create!(:name => 'foo') + @project = @account.projects.create!(:name => 'bar') + end + + it "should allow tenant_id to change inside the block" do + new_account_id = @account.id + 1 + expect{ ActsAsTenant.without_tenant! { @project.account_id = new_account_id } }.to_not raise_error(ActsAsTenant::Errors::TenantIsImmutable) + expect(@project.account_id).to eq new_account_id + end + end + end + # Tenant required context "tenant required" do before do