activerecord-multi-tenant 1.0.1 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +2 -0
 - data/.travis.yml +8 -14
 - data/Appraisals +28 -20
 - data/CHANGELOG.md +29 -0
 - data/Gemfile.lock +85 -67
 - data/README.md +1 -1
 - data/activerecord-multi-tenant.gemspec +1 -1
 - data/gemfiles/.bundle/config +2 -0
 - data/gemfiles/active_record_5.2.gemfile +10 -2
 - data/gemfiles/active_record_5.2.gemfile.lock +104 -98
 - data/gemfiles/{active_record_5.1.gemfile → active_record_6.0.gemfile} +2 -2
 - data/gemfiles/active_record_6.0.gemfile.lock +198 -0
 - data/gemfiles/{rails_4.1.gemfile → active_record_6.1.gemfile} +2 -2
 - data/gemfiles/active_record_6.1.gemfile.lock +198 -0
 - data/gemfiles/rails_5.2.gemfile +10 -2
 - data/gemfiles/rails_5.2.gemfile.lock +109 -103
 - data/gemfiles/{rails_5.0.gemfile → rails_6.0.gemfile} +2 -2
 - data/gemfiles/rails_6.0.gemfile.lock +198 -0
 - data/gemfiles/{rails_5.1.gemfile → rails_6.1.gemfile} +2 -2
 - data/gemfiles/rails_6.1.gemfile.lock +198 -0
 - data/lib/activerecord-multi-tenant.rb +1 -0
 - data/lib/activerecord-multi-tenant/arel_visitors_depth_first.rb +200 -0
 - data/lib/activerecord-multi-tenant/controller_extensions.rb +2 -6
 - data/lib/activerecord-multi-tenant/copy_from_client.rb +2 -2
 - data/lib/activerecord-multi-tenant/migrations.rb +2 -2
 - data/lib/activerecord-multi-tenant/model_extensions.rb +13 -14
 - data/lib/activerecord-multi-tenant/multi_tenant.rb +9 -0
 - data/lib/activerecord-multi-tenant/persistence_extension.rb +13 -0
 - data/lib/activerecord-multi-tenant/query_rewriter.rb +60 -104
 - data/lib/activerecord-multi-tenant/sidekiq.rb +2 -1
 - data/lib/activerecord-multi-tenant/version.rb +1 -1
 - data/spec/activerecord-multi-tenant/controller_extensions_spec.rb +19 -24
 - data/spec/activerecord-multi-tenant/model_extensions_spec.rb +54 -104
 - data/spec/activerecord-multi-tenant/query_rewriter_spec.rb +8 -0
 - data/spec/activerecord-multi-tenant/record_finding_spec.rb +36 -0
 - data/spec/activerecord-multi-tenant/record_modifications_spec.rb +60 -3
 - data/spec/activerecord-multi-tenant/schema_dumper_tester.rb +0 -0
 - data/spec/activerecord-multi-tenant/sidekiq_spec.rb +4 -4
 - data/spec/schema.rb +1 -4
 - data/spec/spec_helper.rb +1 -6
 - metadata +17 -17
 - data/gemfiles/active_record_5.1.gemfile.lock +0 -173
 - data/gemfiles/rails_4.0.gemfile +0 -8
 - data/gemfiles/rails_4.0.gemfile.lock +0 -141
 - data/gemfiles/rails_4.1.gemfile.lock +0 -146
 - data/gemfiles/rails_4.2.gemfile +0 -8
 - data/gemfiles/rails_4.2.gemfile.lock +0 -169
 - data/gemfiles/rails_5.0.gemfile.lock +0 -175
 - data/gemfiles/rails_5.1.gemfile.lock +0 -175
 
| 
         @@ -20,10 +20,6 @@ module MultiTenant 
     | 
|
| 
       20 
20 
     | 
    
         
             
              end
         
     | 
| 
       21 
21 
     | 
    
         
             
            end
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
               
     | 
| 
       25 
     | 
    
         
            -
            end
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
            if defined?(ActionController::API)
         
     | 
| 
       28 
     | 
    
         
            -
              ActionController::API.extend MultiTenant::ControllerExtensions
         
     | 
| 
      
 23 
     | 
    
         
            +
            ActiveSupport.on_load(:action_controller) do |base|
         
     | 
| 
      
 24 
     | 
    
         
            +
              base.extend MultiTenant::ControllerExtensions
         
     | 
| 
       29 
25 
     | 
    
         
             
            end
         
     | 
| 
         @@ -44,10 +44,10 @@ module ActiveRecord 
     | 
|
| 
       44 
44 
     | 
    
         
             
                module SchemaStatements
         
     | 
| 
       45 
45 
     | 
    
         
             
                  alias :orig_create_table :create_table
         
     | 
| 
       46 
46 
     | 
    
         
             
                  def create_table(table_name, options = {}, &block)
         
     | 
| 
       47 
     | 
    
         
            -
                    ret = orig_create_table(table_name, options.except(:partition_key), &block)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    ret = orig_create_table(table_name, **options.except(:partition_key), &block)
         
     | 
| 
       48 
48 
     | 
    
         
             
                    if options[:partition_key] && options[:partition_key].to_s != 'id'
         
     | 
| 
       49 
49 
     | 
    
         
             
                      execute "ALTER TABLE #{table_name} DROP CONSTRAINT #{table_name}_pkey"
         
     | 
| 
       50 
     | 
    
         
            -
                      execute "ALTER TABLE #{table_name} ADD PRIMARY KEY( 
     | 
| 
      
 50 
     | 
    
         
            +
                      execute "ALTER TABLE #{table_name} ADD PRIMARY KEY(\"#{options[:partition_key]}\", id)"
         
     | 
| 
       51 
51 
     | 
    
         
             
                    end
         
     | 
| 
       52 
52 
     | 
    
         
             
                    ret
         
     | 
| 
       53 
53 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -24,11 +24,6 @@ module MultiTenant 
     | 
|
| 
       24 
24 
     | 
    
         
             
                      def primary_key
         
     | 
| 
       25 
25 
     | 
    
         
             
                        return @primary_key if @primary_key
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                        if ::ActiveRecord::VERSION::MAJOR < 5
         
     | 
| 
       28 
     | 
    
         
            -
                          @primary_key = super || DEFAULT_ID_FIELD
         
     | 
| 
       29 
     | 
    
         
            -
                          return @primary_key if connection.schema_cache.columns_hash(table_name).include? @primary_key
         
     | 
| 
       30 
     | 
    
         
            -
                        end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
27 
     | 
    
         
             
                        primary_object_keys = Array.wrap(connection.schema_cache.primary_keys(table_name)) - [partition_key]
         
     | 
| 
       33 
28 
     | 
    
         | 
| 
       34 
29 
     | 
    
         
             
                        if primary_object_keys.size == 1
         
     | 
| 
         @@ -54,7 +49,7 @@ module MultiTenant 
     | 
|
| 
       54 
49 
     | 
    
         | 
| 
       55 
50 
     | 
    
         
             
                    # Create an implicit belongs_to association only if tenant class exists
         
     | 
| 
       56 
51 
     | 
    
         
             
                    if MultiTenant.tenant_klass_defined?(tenant_name)
         
     | 
| 
       57 
     | 
    
         
            -
                      belongs_to tenant_name, options.slice(:class_name, :inverse_of).merge(foreign_key: options[:partition_key])
         
     | 
| 
      
 52 
     | 
    
         
            +
                      belongs_to tenant_name, **options.slice(:class_name, :inverse_of).merge(foreign_key: options[:partition_key])
         
     | 
| 
       58 
53 
     | 
    
         
             
                    end
         
     | 
| 
       59 
54 
     | 
    
         | 
| 
       60 
55 
     | 
    
         
             
                    # New instances should have the tenant set
         
     | 
| 
         @@ -126,16 +121,20 @@ module MultiTenant 
     | 
|
| 
       126 
121 
     | 
    
         
             
              end
         
     | 
| 
       127 
122 
     | 
    
         
             
            end
         
     | 
| 
       128 
123 
     | 
    
         | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
               
     | 
| 
      
 124 
     | 
    
         
            +
            ActiveSupport.on_load(:active_record) do |base|
         
     | 
| 
      
 125 
     | 
    
         
            +
              base.extend MultiTenant::ModelExtensionsClassMethods
         
     | 
| 
       131 
126 
     | 
    
         
             
            end
         
     | 
| 
       132 
127 
     | 
    
         | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
               
     | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
     | 
    
         
            -
                 
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
             
     | 
| 
      
 128 
     | 
    
         
            +
            class ActiveRecord::Associations::Association
         
     | 
| 
      
 129 
     | 
    
         
            +
              alias skip_statement_cache_orig skip_statement_cache?
         
     | 
| 
      
 130 
     | 
    
         
            +
              def skip_statement_cache?(*scope)
         
     | 
| 
      
 131 
     | 
    
         
            +
                return true if klass.respond_to?(:scoped_by_tenant?) && klass.scoped_by_tenant?
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                if reflection.through_reflection
         
     | 
| 
      
 134 
     | 
    
         
            +
                  through_klass = reflection.through_reflection.klass
         
     | 
| 
      
 135 
     | 
    
         
            +
                  return true if through_klass.respond_to?(:scoped_by_tenant?) && through_klass.scoped_by_tenant?
         
     | 
| 
       139 
136 
     | 
    
         
             
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                skip_statement_cache_orig(*scope)
         
     | 
| 
       140 
139 
     | 
    
         
             
              end
         
     | 
| 
       141 
140 
     | 
    
         
             
            end
         
     | 
| 
         @@ -33,6 +33,15 @@ module MultiTenant 
     | 
|
| 
       33 
33 
     | 
    
         
             
                @@multi_tenant_models[table_name.to_s]
         
     | 
| 
       34 
34 
     | 
    
         
             
              end
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
      
 36 
     | 
    
         
            +
              def self.multi_tenant_model_for_arel(arel)
         
     | 
| 
      
 37 
     | 
    
         
            +
                return nil unless arel.respond_to?(:ast)
         
     | 
| 
      
 38 
     | 
    
         
            +
                if arel.ast.relation.is_a? Arel::Nodes::JoinSource
         
     | 
| 
      
 39 
     | 
    
         
            +
                  MultiTenant.multi_tenant_model_for_table(arel.ast.relation.left.table_name)
         
     | 
| 
      
 40 
     | 
    
         
            +
                else
         
     | 
| 
      
 41 
     | 
    
         
            +
                  MultiTenant.multi_tenant_model_for_table(arel.ast.relation.table_name)
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
       36 
45 
     | 
    
         
             
              def self.current_tenant=(tenant)
         
     | 
| 
       37 
46 
     | 
    
         
             
                RequestStore.store[:current_tenant] = tenant
         
     | 
| 
       38 
47 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Persistence
         
     | 
| 
      
 3 
     | 
    
         
            +
                alias :delete_orig :delete
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def delete
         
     | 
| 
      
 6 
     | 
    
         
            +
                  if MultiTenant.multi_tenant_model_for_table(self.class.table_name).present? && persisted? && MultiTenant.current_tenant_id.nil?
         
     | 
| 
      
 7 
     | 
    
         
            +
                    MultiTenant.with(self.public_send(self.class.partition_key)) { delete_orig }
         
     | 
| 
      
 8 
     | 
    
         
            +
                  else
         
     | 
| 
      
 9 
     | 
    
         
            +
                    delete_orig
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,4 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'active_record'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative "./arel_visitors_depth_first.rb" unless Arel::Visitors.const_defined?(:DepthFirst)
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
4 
     | 
    
         
             
            module MultiTenant
         
     | 
| 
       4 
5 
     | 
    
         
             
              class Table
         
     | 
| 
         @@ -31,6 +32,7 @@ module MultiTenant 
     | 
|
| 
       31 
32 
     | 
    
         
             
                  @arel_node = arel_node
         
     | 
| 
       32 
33 
     | 
    
         
             
                  @known_relations = []
         
     | 
| 
       33 
34 
     | 
    
         
             
                  @handled_relations = []
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @discovering = false
         
     | 
| 
       34 
36 
     | 
    
         
             
                end
         
     | 
| 
       35 
37 
     | 
    
         | 
| 
       36 
38 
     | 
    
         
             
                def discover_relations
         
     | 
| 
         @@ -54,7 +56,7 @@ module MultiTenant 
     | 
|
| 
       54 
56 
     | 
    
         
             
                end
         
     | 
| 
       55 
57 
     | 
    
         
             
              end
         
     | 
| 
       56 
58 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
              class ArelTenantVisitor < Arel::Visitors::DepthFirst
         
     | 
| 
      
 59 
     | 
    
         
            +
              class ArelTenantVisitor < Arel::Visitors.const_defined?(:DepthFirst) ? Arel::Visitors::DepthFirst : ::MultiTenant::ArelVisitorsDepthFirst
         
     | 
| 
       58 
60 
     | 
    
         
             
                def initialize(arel)
         
     | 
| 
       59 
61 
     | 
    
         
             
                  super(Proc.new {})
         
     | 
| 
       60 
62 
     | 
    
         
             
                  @statement_node_id = nil
         
     | 
| 
         @@ -149,21 +151,27 @@ module MultiTenant 
     | 
|
| 
       149 
151 
     | 
    
         
             
                end
         
     | 
| 
       150 
152 
     | 
    
         
             
              end
         
     | 
| 
       151 
153 
     | 
    
         | 
| 
       152 
     | 
    
         
            -
              class  
     | 
| 
      
 154 
     | 
    
         
            +
              class BaseTenantEnforcementClause < Arel::Nodes::Node
         
     | 
| 
       153 
155 
     | 
    
         
             
                attr_reader :tenant_attribute
         
     | 
| 
       154 
156 
     | 
    
         
             
                def initialize(tenant_attribute)
         
     | 
| 
       155 
157 
     | 
    
         
             
                  @tenant_attribute = tenant_attribute
         
     | 
| 
      
 158 
     | 
    
         
            +
                  @tenant_model = MultiTenant.multi_tenant_model_for_table(tenant_attribute.relation.table_name)
         
     | 
| 
       156 
159 
     | 
    
         
             
                end
         
     | 
| 
       157 
160 
     | 
    
         | 
| 
       158 
161 
     | 
    
         
             
                def to_s; to_sql; end
         
     | 
| 
       159 
162 
     | 
    
         
             
                def to_str; to_sql; end
         
     | 
| 
       160 
163 
     | 
    
         | 
| 
       161 
164 
     | 
    
         
             
                def to_sql(*)
         
     | 
| 
       162 
     | 
    
         
            -
                   
     | 
| 
      
 165 
     | 
    
         
            +
                  collector = Arel::Collectors::SQLString.new
         
     | 
| 
      
 166 
     | 
    
         
            +
                  collector = @tenant_model.connection.visitor.accept tenant_arel, collector
         
     | 
| 
      
 167 
     | 
    
         
            +
                  collector.value
         
     | 
| 
       163 
168 
     | 
    
         
             
                end
         
     | 
| 
       164 
169 
     | 
    
         | 
| 
       165 
     | 
    
         
            -
                private
         
     | 
| 
       166 
170 
     | 
    
         | 
| 
      
 171 
     | 
    
         
            +
              end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
              class TenantEnforcementClause < BaseTenantEnforcementClause
         
     | 
| 
      
 174 
     | 
    
         
            +
                private
         
     | 
| 
       167 
175 
     | 
    
         
             
                def tenant_arel
         
     | 
| 
       168 
176 
     | 
    
         
             
                  if defined?(Arel::Nodes::Quoted)
         
     | 
| 
       169 
177 
     | 
    
         
             
                    @tenant_attribute.eq(Arel::Nodes::Quoted.new(MultiTenant.current_tenant_id))
         
     | 
| 
         @@ -174,24 +182,15 @@ module MultiTenant 
     | 
|
| 
       174 
182 
     | 
    
         
             
              end
         
     | 
| 
       175 
183 
     | 
    
         | 
| 
       176 
184 
     | 
    
         | 
| 
       177 
     | 
    
         
            -
              class TenantJoinEnforcementClause <  
     | 
| 
       178 
     | 
    
         
            -
                attr_reader :tenant_attribute
         
     | 
| 
      
 185 
     | 
    
         
            +
              class TenantJoinEnforcementClause < BaseTenantEnforcementClause
         
     | 
| 
       179 
186 
     | 
    
         
             
                attr_reader :table_left
         
     | 
| 
       180 
187 
     | 
    
         
             
                def initialize(tenant_attribute, table_left)
         
     | 
| 
      
 188 
     | 
    
         
            +
                  super(tenant_attribute)
         
     | 
| 
       181 
189 
     | 
    
         
             
                  @table_left = table_left
         
     | 
| 
       182 
190 
     | 
    
         
             
                  @model_left = MultiTenant.multi_tenant_model_for_table(table_left.table_name)
         
     | 
| 
       183 
     | 
    
         
            -
                  @tenant_attribute = tenant_attribute
         
     | 
| 
       184 
     | 
    
         
            -
                end
         
     | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
       186 
     | 
    
         
            -
                def to_s; to_sql; end
         
     | 
| 
       187 
     | 
    
         
            -
                def to_str; to_sql; end
         
     | 
| 
       188 
     | 
    
         
            -
             
     | 
| 
       189 
     | 
    
         
            -
                def to_sql(*)
         
     | 
| 
       190 
     | 
    
         
            -
                  tenant_arel.to_sql
         
     | 
| 
       191 
191 
     | 
    
         
             
                end
         
     | 
| 
       192 
192 
     | 
    
         | 
| 
       193 
193 
     | 
    
         
             
                private
         
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
194 
     | 
    
         
             
                def tenant_arel
         
     | 
| 
       196 
195 
     | 
    
         
             
                  @tenant_attribute.eq(@table_left[@model_left.partition_key])
         
     | 
| 
       197 
196 
     | 
    
         
             
                end
         
     | 
| 
         @@ -199,23 +198,12 @@ module MultiTenant 
     | 
|
| 
       199 
198 
     | 
    
         | 
| 
       200 
199 
     | 
    
         | 
| 
       201 
200 
     | 
    
         
             
              module TenantValueVisitor
         
     | 
| 
       202 
     | 
    
         
            -
                 
     | 
| 
       203 
     | 
    
         
            -
                   
     | 
| 
       204 
     | 
    
         
            -
             
     | 
| 
       205 
     | 
    
         
            -
                  end
         
     | 
| 
       206 
     | 
    
         
            -
             
     | 
| 
       207 
     | 
    
         
            -
                  def visit_MultiTenant_TenantJoinEnforcementClause(o, collector)
         
     | 
| 
       208 
     | 
    
         
            -
                    collector << o
         
     | 
| 
       209 
     | 
    
         
            -
                  end
         
     | 
| 
       210 
     | 
    
         
            -
             
     | 
| 
       211 
     | 
    
         
            -
                else
         
     | 
| 
       212 
     | 
    
         
            -
                  def visit_MultiTenant_TenantEnforcementClause(o, a = nil)
         
     | 
| 
       213 
     | 
    
         
            -
                    o
         
     | 
| 
       214 
     | 
    
         
            -
                  end
         
     | 
| 
      
 201 
     | 
    
         
            +
                def visit_MultiTenant_TenantEnforcementClause(o, collector)
         
     | 
| 
      
 202 
     | 
    
         
            +
                  collector << o
         
     | 
| 
      
 203 
     | 
    
         
            +
                end
         
     | 
| 
       215 
204 
     | 
    
         | 
| 
       216 
     | 
    
         
            -
             
     | 
| 
       217 
     | 
    
         
            -
             
     | 
| 
       218 
     | 
    
         
            -
                  end
         
     | 
| 
      
 205 
     | 
    
         
            +
                def visit_MultiTenant_TenantJoinEnforcementClause(o, collector)
         
     | 
| 
      
 206 
     | 
    
         
            +
                  collector << o
         
     | 
| 
       219 
207 
     | 
    
         
             
                end
         
     | 
| 
       220 
208 
     | 
    
         
             
              end
         
     | 
| 
       221 
209 
     | 
    
         | 
| 
         @@ -238,22 +226,20 @@ module MultiTenant 
     | 
|
| 
       238 
226 
     | 
    
         
             
                  delete
         
     | 
| 
       239 
227 
     | 
    
         
             
                end
         
     | 
| 
       240 
228 
     | 
    
         | 
| 
       241 
     | 
    
         
            -
                 
     | 
| 
       242 
     | 
    
         
            -
                   
     | 
| 
       243 
     | 
    
         
            -
             
     | 
| 
       244 
     | 
    
         
            -
                     
     | 
| 
       245 
     | 
    
         
            -
                      arel.where(MultiTenant::TenantEnforcementClause.new(model.arel_table[model.partition_key]))
         
     | 
| 
       246 
     | 
    
         
            -
                    end
         
     | 
| 
       247 
     | 
    
         
            -
                    super(arel, name, binds)
         
     | 
| 
      
 229 
     | 
    
         
            +
                def update(arel, name = nil, binds = [])
         
     | 
| 
      
 230 
     | 
    
         
            +
                  model = MultiTenant.multi_tenant_model_for_arel(arel)
         
     | 
| 
      
 231 
     | 
    
         
            +
                  if model.present? && !MultiTenant.with_write_only_mode_enabled? && MultiTenant.current_tenant_id.present?
         
     | 
| 
      
 232 
     | 
    
         
            +
                    arel.where(MultiTenant::TenantEnforcementClause.new(model.arel_table[model.partition_key]))
         
     | 
| 
       248 
233 
     | 
    
         
             
                  end
         
     | 
| 
      
 234 
     | 
    
         
            +
                  super(arel, name, binds)
         
     | 
| 
      
 235 
     | 
    
         
            +
                end
         
     | 
| 
       249 
236 
     | 
    
         | 
| 
       250 
     | 
    
         
            -
             
     | 
| 
       251 
     | 
    
         
            -
             
     | 
| 
       252 
     | 
    
         
            -
             
     | 
| 
       253 
     | 
    
         
            -
             
     | 
| 
       254 
     | 
    
         
            -
                    end
         
     | 
| 
       255 
     | 
    
         
            -
                    super(arel, name, binds)
         
     | 
| 
      
 237 
     | 
    
         
            +
                def delete(arel, name = nil, binds = [])
         
     | 
| 
      
 238 
     | 
    
         
            +
                  model = MultiTenant.multi_tenant_model_for_arel(arel)
         
     | 
| 
      
 239 
     | 
    
         
            +
                  if model.present? && !MultiTenant.with_write_only_mode_enabled? && MultiTenant.current_tenant_id.present?
         
     | 
| 
      
 240 
     | 
    
         
            +
                    arel.where(MultiTenant::TenantEnforcementClause.new(model.arel_table[model.partition_key]))
         
     | 
| 
       256 
241 
     | 
    
         
             
                  end
         
     | 
| 
      
 242 
     | 
    
         
            +
                  super(arel, name, binds)
         
     | 
| 
       257 
243 
     | 
    
         
             
                end
         
     | 
| 
       258 
244 
     | 
    
         
             
              end
         
     | 
| 
       259 
245 
     | 
    
         
             
            end
         
     | 
| 
         @@ -296,7 +282,6 @@ module ActiveRecord 
     | 
|
| 
       296 
282 
     | 
    
         
             
                        end
         
     | 
| 
       297 
283 
     | 
    
         | 
| 
       298 
284 
     | 
    
         
             
                        if node.is_a?(Arel::Nodes::SelectCore) || node.is_a?(Arel::Nodes::Join)
         
     | 
| 
       299 
     | 
    
         
            -
             
     | 
| 
       300 
285 
     | 
    
         
             
                          if node.is_a?Arel::Nodes::Join
         
     | 
| 
       301 
286 
     | 
    
         
             
                            node_list = [node]
         
     | 
| 
       302 
287 
     | 
    
         
             
                          else
         
     | 
| 
         @@ -304,14 +289,18 @@ module ActiveRecord 
     | 
|
| 
       304 
289 
     | 
    
         
             
                          end
         
     | 
| 
       305 
290 
     | 
    
         | 
| 
       306 
291 
     | 
    
         
             
                          node_list.select{ |n| n.is_a? Arel::Nodes::Join }.each do |node_join|
         
     | 
| 
       307 
     | 
    
         
            -
                            if !node_join.right || 
     | 
| 
      
 292 
     | 
    
         
            +
                            if (!node_join.right ||
         
     | 
| 
      
 293 
     | 
    
         
            +
                                (ActiveRecord::VERSION::MAJOR == 5 &&
         
     | 
| 
      
 294 
     | 
    
         
            +
                                 !node_join.right.expr.right.is_a?(Arel::Attributes::Attribute)))
         
     | 
| 
       308 
295 
     | 
    
         
             
                              next
         
     | 
| 
       309 
296 
     | 
    
         
             
                            end
         
     | 
| 
       310 
297 
     | 
    
         | 
| 
       311 
     | 
    
         
            -
                            relation_right = node_join 
     | 
| 
       312 
     | 
    
         
            -
             
     | 
| 
       313 
     | 
    
         
            -
                             
     | 
| 
      
 298 
     | 
    
         
            +
                            relation_right, relation_left = relations_from_node_join(node_join)
         
     | 
| 
      
 299 
     | 
    
         
            +
             
     | 
| 
      
 300 
     | 
    
         
            +
                            next unless relation_right && relation_left
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
       314 
302 
     | 
    
         
             
                            model_right = MultiTenant.multi_tenant_model_for_table(relation_left.table_name)
         
     | 
| 
      
 303 
     | 
    
         
            +
                            model_left = MultiTenant.multi_tenant_model_for_table(relation_right.table_name)
         
     | 
| 
       315 
304 
     | 
    
         
             
                            if model_right && model_left
         
     | 
| 
       316 
305 
     | 
    
         
             
                              join_enforcement_clause = MultiTenant::TenantJoinEnforcementClause.new(relation_left[model_left.partition_key], relation_right)
         
     | 
| 
       317 
306 
     | 
    
         
             
                              node_join.right.expr = node_join.right.expr.and(join_enforcement_clause)
         
     | 
| 
         @@ -324,69 +313,36 @@ module ActiveRecord 
     | 
|
| 
       324 
313 
     | 
    
         | 
| 
       325 
314 
     | 
    
         
             
                  arel
         
     | 
| 
       326 
315 
     | 
    
         
             
                end
         
     | 
| 
       327 
     | 
    
         
            -
              end
         
     | 
| 
       328 
     | 
    
         
            -
            end
         
     | 
| 
       329 
316 
     | 
    
         | 
| 
       330 
     | 
    
         
            -
             
     | 
| 
       331 
     | 
    
         
            -
             
     | 
| 
       332 
     | 
    
         
            -
             
     | 
| 
       333 
     | 
    
         
            -
             
     | 
| 
       334 
     | 
    
         
            -
             
     | 
| 
       335 
     | 
    
         
            -
                def find_by(*args)
         
     | 
| 
       336 
     | 
    
         
            -
                  return super unless respond_to?(:scoped_by_tenant?) && scoped_by_tenant?
         
     | 
| 
       337 
     | 
    
         
            -
             
     | 
| 
       338 
     | 
    
         
            -
                  # This duplicates a bunch of code from AR's find() method
         
     | 
| 
       339 
     | 
    
         
            -
                  return super if current_scope || !(Hash === args.first) || reflect_on_all_aggregations.any?
         
     | 
| 
       340 
     | 
    
         
            -
                  return super if default_scopes.any?
         
     | 
| 
       341 
     | 
    
         
            -
             
     | 
| 
       342 
     | 
    
         
            -
                  hash = args.first
         
     | 
| 
      
 317 
     | 
    
         
            +
                private
         
     | 
| 
      
 318 
     | 
    
         
            +
                def relations_from_node_join(node_join)
         
     | 
| 
      
 319 
     | 
    
         
            +
                  if ActiveRecord::VERSION::MAJOR == 5 || node_join.right.expr.is_a?(Arel::Nodes::Equality)
         
     | 
| 
      
 320 
     | 
    
         
            +
                    return node_join.right.expr.right.relation, node_join.right.expr.left.relation
         
     | 
| 
      
 321 
     | 
    
         
            +
                  end
         
     | 
| 
       343 
322 
     | 
    
         | 
| 
       344 
     | 
    
         
            -
                   
     | 
| 
       345 
     | 
    
         
            -
                  return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
         
     | 
| 
      
 323 
     | 
    
         
            +
                  children = node_join.right.expr.children
         
     | 
| 
       346 
324 
     | 
    
         | 
| 
       347 
     | 
    
         
            -
                   
     | 
| 
      
 325 
     | 
    
         
            +
                  tenant_applied = children.any?(MultiTenant::TenantEnforcementClause) || children.any?(MultiTenant::TenantJoinEnforcementClause)
         
     | 
| 
      
 326 
     | 
    
         
            +
                  if tenant_applied || children.empty?
         
     | 
| 
      
 327 
     | 
    
         
            +
                    return nil, nil
         
     | 
| 
      
 328 
     | 
    
         
            +
                  end
         
     | 
| 
       348 
329 
     | 
    
         | 
| 
       349 
     | 
    
         
            -
                   
     | 
| 
       350 
     | 
    
         
            -
             
     | 
| 
      
 330 
     | 
    
         
            +
                  if children[0].right.respond_to?('relation') && children[0].left.respond_to?('relation')
         
     | 
| 
      
 331 
     | 
    
         
            +
                    return children[0].right.relation, children[0].left.relation
         
     | 
| 
      
 332 
     | 
    
         
            +
                  end
         
     | 
| 
       351 
333 
     | 
    
         | 
| 
       352 
     | 
    
         
            -
                   
     | 
| 
      
 334 
     | 
    
         
            +
                  return nil, nil
         
     | 
| 
       353 
335 
     | 
    
         
             
                end
         
     | 
| 
      
 336 
     | 
    
         
            +
              end
         
     | 
| 
      
 337 
     | 
    
         
            +
            end
         
     | 
| 
       354 
338 
     | 
    
         | 
| 
       355 
     | 
    
         
            -
             
     | 
| 
       356 
     | 
    
         
            -
             
     | 
| 
       357 
     | 
    
         
            -
             
     | 
| 
       358 
     | 
    
         
            -
             
     | 
| 
       359 
     | 
    
         
            -
                  return super unless ids.length == 1
         
     | 
| 
       360 
     | 
    
         
            -
                  return super if ids.first.kind_of?(Symbol)
         
     | 
| 
       361 
     | 
    
         
            -
                  return super if block_given? ||
         
     | 
| 
       362 
     | 
    
         
            -
                                  primary_key.nil? ||
         
     | 
| 
       363 
     | 
    
         
            -
                                  default_scopes.any? ||
         
     | 
| 
       364 
     | 
    
         
            -
                                  current_scope ||
         
     | 
| 
       365 
     | 
    
         
            -
                                  columns_hash.include?(inheritance_column) ||
         
     | 
| 
       366 
     | 
    
         
            -
                                  ids.first.kind_of?(Array)
         
     | 
| 
       367 
     | 
    
         
            -
             
     | 
| 
       368 
     | 
    
         
            -
                  id = ids.first
         
     | 
| 
       369 
     | 
    
         
            -
                    if ActiveRecord::Base === id
         
     | 
| 
       370 
     | 
    
         
            -
                      id = id.id
         
     | 
| 
       371 
     | 
    
         
            -
                      ActiveSupport::Deprecation.warn(<<-MSG.squish)
         
     | 
| 
       372 
     | 
    
         
            -
                        You are passing an instance of ActiveRecord::Base to `find`.
         
     | 
| 
       373 
     | 
    
         
            -
                        Please pass the id of the object by calling `.id`
         
     | 
| 
       374 
     | 
    
         
            -
                      MSG
         
     | 
| 
       375 
     | 
    
         
            -
                    end
         
     | 
| 
       376 
     | 
    
         
            -
                  key = primary_key
         
     | 
| 
       377 
     | 
    
         
            -
             
     | 
| 
       378 
     | 
    
         
            -
                  # Ensure we never use the cached version
         
     | 
| 
       379 
     | 
    
         
            -
                  find_by_statement_cache.synchronize { find_by_statement_cache[key] = nil }
         
     | 
| 
       380 
     | 
    
         
            -
             
     | 
| 
       381 
     | 
    
         
            -
                  super
         
     | 
| 
       382 
     | 
    
         
            -
                end
         
     | 
| 
       383 
     | 
    
         
            -
              elsif ActiveRecord::VERSION::MAJOR > 4
         
     | 
| 
       384 
     | 
    
         
            -
                def cached_find_by_statement(key, &block)
         
     | 
| 
       385 
     | 
    
         
            -
                  return super unless respond_to?(:scoped_by_tenant?) && scoped_by_tenant?
         
     | 
| 
      
 339 
     | 
    
         
            +
            require 'active_record/base'
         
     | 
| 
      
 340 
     | 
    
         
            +
            module MultiTenantFindBy
         
     | 
| 
      
 341 
     | 
    
         
            +
              def cached_find_by_statement(key, &block)
         
     | 
| 
      
 342 
     | 
    
         
            +
                return super unless respond_to?(:scoped_by_tenant?) && scoped_by_tenant?
         
     | 
| 
       386 
343 
     | 
    
         | 
| 
       387 
     | 
    
         
            -
             
     | 
| 
       388 
     | 
    
         
            -
             
     | 
| 
       389 
     | 
    
         
            -
                end
         
     | 
| 
      
 344 
     | 
    
         
            +
                key = Array.wrap(key) + [MultiTenant.current_tenant_id.to_s]
         
     | 
| 
      
 345 
     | 
    
         
            +
                super(key, &block)
         
     | 
| 
       390 
346 
     | 
    
         
             
              end
         
     | 
| 
       391 
347 
     | 
    
         
             
            end
         
     | 
| 
       392 
348 
     | 
    
         | 
| 
         @@ -18,7 +18,8 @@ module Sidekiq::Middleware::MultiTenant 
     | 
|
| 
       18 
18 
     | 
    
         
             
              class Server
         
     | 
| 
       19 
19 
     | 
    
         
             
                def call(worker_class, msg, queue)
         
     | 
| 
       20 
20 
     | 
    
         
             
                  if msg.has_key?('multi_tenant')
         
     | 
| 
       21 
     | 
    
         
            -
                     
     | 
| 
      
 21 
     | 
    
         
            +
                    tenant = msg['multi_tenant']['class'].constantize.find(msg['multi_tenant']['id'])
         
     | 
| 
      
 22 
     | 
    
         
            +
                    MultiTenant.with(tenant) do
         
     | 
| 
       22 
23 
     | 
    
         
             
                      yield
         
     | 
| 
       23 
24 
     | 
    
         
             
                    end
         
     | 
| 
       24 
25 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -21,11 +21,7 @@ describe "Controller Extensions", type: :controller do 
     | 
|
| 
       21 
21 
     | 
    
         
             
              describe ApplicationController, type: :controller do
         
     | 
| 
       22 
22 
     | 
    
         
             
                controller do
         
     | 
| 
       23 
23 
     | 
    
         
             
                  def index
         
     | 
| 
       24 
     | 
    
         
            -
                     
     | 
| 
       25 
     | 
    
         
            -
                      render body: 'custom called'
         
     | 
| 
       26 
     | 
    
         
            -
                    else
         
     | 
| 
       27 
     | 
    
         
            -
                      render text: 'custom called'
         
     | 
| 
       28 
     | 
    
         
            -
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
                    render body: 'custom called'
         
     | 
| 
       29 
25 
     | 
    
         
             
                  end
         
     | 
| 
       30 
26 
     | 
    
         
             
                end
         
     | 
| 
       31 
27 
     | 
    
         | 
| 
         @@ -35,30 +31,29 @@ describe "Controller Extensions", type: :controller do 
     | 
|
| 
       35 
31 
     | 
    
         
             
                end
         
     | 
| 
       36 
32 
     | 
    
         
             
              end
         
     | 
| 
       37 
33 
     | 
    
         | 
| 
       38 
     | 
    
         
            -
              if ActionPack::VERSION::MAJOR >= 5
         
     | 
| 
       39 
     | 
    
         
            -
                class APIApplicationController < ActionController::API
         
     | 
| 
       40 
     | 
    
         
            -
                  include Rails.application.routes.url_helpers
         
     | 
| 
       41 
     | 
    
         
            -
                  set_current_tenant_through_filter
         
     | 
| 
       42 
     | 
    
         
            -
                  before_action :your_method_that_finds_the_current_tenant
         
     | 
| 
       43 
34 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
      
 35 
     | 
    
         
            +
              class APIApplicationController < ActionController::API
         
     | 
| 
      
 36 
     | 
    
         
            +
                include Rails.application.routes.url_helpers
         
     | 
| 
      
 37 
     | 
    
         
            +
                set_current_tenant_through_filter
         
     | 
| 
      
 38 
     | 
    
         
            +
                before_action :your_method_that_finds_the_current_tenant
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def your_method_that_finds_the_current_tenant
         
     | 
| 
      
 41 
     | 
    
         
            +
                  current_account = Account.new
         
     | 
| 
      
 42 
     | 
    
         
            +
                  current_account.name = 'account1'
         
     | 
| 
      
 43 
     | 
    
         
            +
                  set_current_tenant(current_account)
         
     | 
| 
       49 
44 
     | 
    
         
             
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
       50 
46 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
              describe APIApplicationController, type: :controller do
         
     | 
| 
      
 48 
     | 
    
         
            +
                controller do
         
     | 
| 
      
 49 
     | 
    
         
            +
                  def index
         
     | 
| 
      
 50 
     | 
    
         
            +
                    render body: 'custom called'
         
     | 
| 
       56 
51 
     | 
    
         
             
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
       57 
53 
     | 
    
         | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                it 'Finds the correct tenant using the filter command' do
         
     | 
| 
      
 55 
     | 
    
         
            +
                  get :index
         
     | 
| 
      
 56 
     | 
    
         
            +
                  expect(MultiTenant.current_tenant.name).to eq 'account1'
         
     | 
| 
       62 
57 
     | 
    
         
             
                end
         
     | 
| 
       63 
58 
     | 
    
         
             
              end
         
     | 
| 
       64 
59 
     | 
    
         
             
            end
         
     |