torque-postgresql 1.1.1 → 2.0.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 +5 -5
- data/Rakefile +5 -2
- data/lib/torque/postgresql.rb +0 -2
- data/lib/torque/postgresql/adapter.rb +0 -1
- data/lib/torque/postgresql/adapter/database_statements.rb +4 -15
- data/lib/torque/postgresql/adapter/schema_creation.rb +13 -23
- data/lib/torque/postgresql/adapter/schema_definitions.rb +7 -21
- data/lib/torque/postgresql/adapter/schema_dumper.rb +71 -11
- data/lib/torque/postgresql/adapter/schema_statements.rb +2 -12
- data/lib/torque/postgresql/associations.rb +0 -3
- data/lib/torque/postgresql/associations/association_scope.rb +18 -61
- data/lib/torque/postgresql/associations/belongs_to_many_association.rb +2 -1
- data/lib/torque/postgresql/associations/preloader.rb +0 -24
- data/lib/torque/postgresql/associations/preloader/association.rb +13 -9
- data/lib/torque/postgresql/auxiliary_statement.rb +12 -17
- data/lib/torque/postgresql/coder.rb +1 -2
- data/lib/torque/postgresql/config.rb +0 -4
- data/lib/torque/postgresql/inheritance.rb +13 -17
- data/lib/torque/postgresql/reflection/abstract_reflection.rb +19 -25
- data/lib/torque/postgresql/relation.rb +11 -16
- data/lib/torque/postgresql/relation/auxiliary_statement.rb +9 -15
- data/lib/torque/postgresql/relation/distinct_on.rb +1 -1
- data/lib/torque/postgresql/schema_cache.rb +19 -11
- data/lib/torque/postgresql/version.rb +1 -1
- data/spec/en.yml +19 -0
- data/spec/factories/authors.rb +6 -0
- data/spec/factories/comments.rb +13 -0
- data/spec/factories/posts.rb +6 -0
- data/spec/factories/tags.rb +5 -0
- data/spec/factories/texts.rb +5 -0
- data/spec/factories/users.rb +6 -0
- data/spec/factories/videos.rb +5 -0
- data/spec/mocks/cache_query.rb +16 -0
- data/spec/mocks/create_table.rb +35 -0
- data/spec/models/activity.rb +3 -0
- data/spec/models/activity_book.rb +4 -0
- data/spec/models/activity_post.rb +7 -0
- data/spec/models/activity_post/sample.rb +4 -0
- data/spec/models/author.rb +4 -0
- data/spec/models/author_journalist.rb +4 -0
- data/spec/models/comment.rb +3 -0
- data/spec/models/course.rb +2 -0
- data/spec/models/geometry.rb +2 -0
- data/spec/models/guest_comment.rb +4 -0
- data/spec/models/post.rb +6 -0
- data/spec/models/tag.rb +2 -0
- data/spec/models/text.rb +2 -0
- data/spec/models/time_keeper.rb +2 -0
- data/spec/models/user.rb +8 -0
- data/spec/models/video.rb +2 -0
- data/spec/schema.rb +141 -0
- data/spec/spec_helper.rb +59 -0
- data/spec/tests/arel_spec.rb +72 -0
- data/spec/tests/auxiliary_statement_spec.rb +593 -0
- data/spec/tests/belongs_to_many_spec.rb +240 -0
- data/spec/tests/coder_spec.rb +367 -0
- data/spec/tests/collector_spec.rb +59 -0
- data/spec/tests/distinct_on_spec.rb +65 -0
- data/spec/tests/enum_set_spec.rb +306 -0
- data/spec/tests/enum_spec.rb +628 -0
- data/spec/tests/geometric_builder_spec.rb +221 -0
- data/spec/tests/has_many_spec.rb +390 -0
- data/spec/tests/interval_spec.rb +167 -0
- data/spec/tests/lazy_spec.rb +24 -0
- data/spec/tests/period_spec.rb +954 -0
- data/spec/tests/quoting_spec.rb +24 -0
- data/spec/tests/range_spec.rb +36 -0
- data/spec/tests/relation_spec.rb +57 -0
- data/spec/tests/table_inheritance_spec.rb +416 -0
- metadata +103 -16
- data/lib/torque/postgresql/associations/join_dependency/join_association.rb +0 -15
- data/lib/torque/postgresql/schema_dumper.rb +0 -88
| @@ -33,7 +33,8 @@ module Torque | |
| 33 33 |  | 
| 34 34 | 
             
                    def ids_writer(new_ids)
         | 
| 35 35 | 
             
                      column = reflection.active_record_primary_key
         | 
| 36 | 
            -
                      owner.update_column | 
| 36 | 
            +
                      command = owner.persisted? ? :update_column : :write_attribute
         | 
| 37 | 
            +
                      owner.public_send(command, column, new_ids.presence)
         | 
| 37 38 | 
             
                      @association_scope = nil
         | 
| 38 39 | 
             
                    end
         | 
| 39 40 |  | 
| @@ -1,25 +1 @@ | |
| 1 1 | 
             
            require_relative 'preloader/association'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            unless Torque::PostgreSQL::AR521
         | 
| 4 | 
            -
              module Torque
         | 
| 5 | 
            -
                module PostgreSQL
         | 
| 6 | 
            -
                  module Associations
         | 
| 7 | 
            -
                    module Preloader
         | 
| 8 | 
            -
                      BelongsToMany = Class.new(::ActiveRecord::Associations::Preloader::HasMany)
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                      def preloader_for(reflection, owners, *)
         | 
| 11 | 
            -
                        return AlreadyLoaded \
         | 
| 12 | 
            -
                          if owners.first.association(reflection.name).loaded?
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                        return BelongsToMany \
         | 
| 15 | 
            -
                          if reflection.macro.eql?(:belongs_to_many)
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                        super
         | 
| 18 | 
            -
                      end
         | 
| 19 | 
            -
                    end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                    ::ActiveRecord::Associations::Preloader.prepend(Preloader)
         | 
| 22 | 
            -
                  end
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
              end
         | 
| 25 | 
            -
            end
         | 
| @@ -8,7 +8,7 @@ module Torque | |
| 8 8 |  | 
| 9 9 | 
             
                      # For reflections connected through an array, make sure to properly
         | 
| 10 10 | 
             
                      # decuple the list of ids and set them as associated with the owner
         | 
| 11 | 
            -
                      def run | 
| 11 | 
            +
                      def run
         | 
| 12 12 | 
             
                        return super unless connected_through_array?
         | 
| 13 13 | 
             
                        send("run_array_for_#{@reflection.macro}")
         | 
| 14 14 | 
             
                      end
         | 
| @@ -18,7 +18,7 @@ module Torque | |
| 18 18 | 
             
                        # Specific run for belongs_many association
         | 
| 19 19 | 
             
                        def run_array_for_belongs_to_many
         | 
| 20 20 | 
             
                          # Add reverse to has_many
         | 
| 21 | 
            -
                          records =  | 
| 21 | 
            +
                          records = groupped_records
         | 
| 22 22 | 
             
                          owners.each do |owner|
         | 
| 23 23 | 
             
                            items = records.values_at(*Array.wrap(owner[owner_key_name]))
         | 
| 24 24 | 
             
                            associate_records_to_owner(owner, items.flatten)
         | 
| @@ -29,7 +29,7 @@ module Torque | |
| 29 29 | 
             
                        def run_array_for_has_many
         | 
| 30 30 | 
             
                          # Add reverse to belongs_to_many
         | 
| 31 31 | 
             
                          records = Hash.new { |h, k| h[k] = [] }
         | 
| 32 | 
            -
                           | 
| 32 | 
            +
                          groupped_records.each do |ids, record|
         | 
| 33 33 | 
             
                            ids.each { |id| records[id].concat(Array.wrap(record)) }
         | 
| 34 34 | 
             
                          end
         | 
| 35 35 |  | 
| @@ -47,14 +47,18 @@ module Torque | |
| 47 47 | 
             
                          scope.where(condition).load(&block)
         | 
| 48 48 | 
             
                        end
         | 
| 49 49 |  | 
| 50 | 
            -
                         | 
| 51 | 
            -
                           | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
                          end
         | 
| 50 | 
            +
                        def associate_records_to_owner(owner, records)
         | 
| 51 | 
            +
                          return super unless connected_through_array?
         | 
| 52 | 
            +
                          association = owner.association(reflection.name)
         | 
| 53 | 
            +
                          association.loaded!
         | 
| 54 | 
            +
                          association.target.concat(records)
         | 
| 56 55 | 
             
                        end
         | 
| 57 56 |  | 
| 57 | 
            +
                        def groupped_records
         | 
| 58 | 
            +
                          preloaded_records.group_by do |record|
         | 
| 59 | 
            +
                            convert_key(record[association_key_name])
         | 
| 60 | 
            +
                          end
         | 
| 61 | 
            +
                        end
         | 
| 58 62 | 
             
                    end
         | 
| 59 63 |  | 
| 60 64 | 
             
                    ::ActiveRecord::Associations::Preloader::Association.prepend(Association)
         | 
| @@ -31,11 +31,12 @@ module Torque | |
| 31 31 | 
             
                    end
         | 
| 32 32 |  | 
| 33 33 | 
             
                    # Fast access to statement build
         | 
| 34 | 
            -
                    def build(statement, base, options = nil, bound_attributes = [])
         | 
| 34 | 
            +
                    def build(statement, base, options = nil, bound_attributes = [], join_sources = [])
         | 
| 35 35 | 
             
                      klass = instantiate(statement, base, options)
         | 
| 36 36 | 
             
                      result = klass.build(base)
         | 
| 37 37 |  | 
| 38 38 | 
             
                      bound_attributes.concat(klass.bound_attributes)
         | 
| 39 | 
            +
                      join_sources.concat(klass.join_sources)
         | 
| 39 40 | 
             
                      result
         | 
| 40 41 | 
             
                    end
         | 
| 41 42 |  | 
| @@ -105,7 +106,7 @@ module Torque | |
| 105 106 | 
             
                  delegate :config, :table, :table_name, :relation, :configure, :relation_query?,
         | 
| 106 107 | 
             
                    to: :class
         | 
| 107 108 |  | 
| 108 | 
            -
                  attr_reader :bound_attributes
         | 
| 109 | 
            +
                  attr_reader :bound_attributes, :join_sources
         | 
| 109 110 |  | 
| 110 111 | 
             
                  # Start a new auxiliary statement giving extra options
         | 
| 111 112 | 
             
                  def initialize(*args)
         | 
| @@ -117,15 +118,21 @@ module Torque | |
| 117 118 | 
             
                    @where = options.fetch(:where, {})
         | 
| 118 119 | 
             
                    @select = options.fetch(:select, {})
         | 
| 119 120 | 
             
                    @join_type = options.fetch(:join_type, nil)
         | 
| 121 | 
            +
             | 
| 120 122 | 
             
                    @bound_attributes = []
         | 
| 123 | 
            +
                    @join_sources = []
         | 
| 121 124 | 
             
                  end
         | 
| 122 125 |  | 
| 123 126 | 
             
                  # Build the statement on the given arel and return the WITH statement
         | 
| 124 127 | 
             
                  def build(base)
         | 
| 128 | 
            +
                    @bound_attributes.clear
         | 
| 129 | 
            +
                    @join_sources.clear
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    # Prepare all the data for the statement
         | 
| 125 132 | 
             
                    prepare(base)
         | 
| 126 133 |  | 
| 127 134 | 
             
                    # Add the join condition to the list
         | 
| 128 | 
            -
                     | 
| 135 | 
            +
                    @join_sources << build_join(base)
         | 
| 129 136 |  | 
| 130 137 | 
             
                    # Return the statement with its dependencies
         | 
| 131 138 | 
             
                    [@dependencies, ::Arel::Nodes::As.new(table, build_query(base))]
         | 
| @@ -204,19 +211,7 @@ module Torque | |
| 204 211 | 
             
                          foreign_table = ::Arel::Table.new(association.plural_name)
         | 
| 205 212 | 
             
                        end
         | 
| 206 213 |  | 
| 207 | 
            -
                         | 
| 208 | 
            -
                        # Possibilities:
         | 
| 209 | 
            -
                        # table
         | 
| 210 | 
            -
                        # table, foreign_klass
         | 
| 211 | 
            -
                        # table, foreign_table, foreign_klass
         | 
| 212 | 
            -
                        if association.respond_to?(:join_scope)
         | 
| 213 | 
            -
                          arity = association.method(:join_scope).arity
         | 
| 214 | 
            -
                          args = [@query.arel_table, foreign_table, base]
         | 
| 215 | 
            -
                          args.delete_at(1) if arity <= 2 # Delete foreign_table
         | 
| 216 | 
            -
                          args.delete_at(1) if arity <= 1 # Delete base (foreign_klass)
         | 
| 217 | 
            -
             | 
| 218 | 
            -
                          @query.merge(association.join_scope(*args))
         | 
| 219 | 
            -
                        end
         | 
| 214 | 
            +
                        @query.merge(association.join_scope(@query.arel_table, foreign_table, base))
         | 
| 220 215 |  | 
| 221 216 | 
             
                        # Add the join constraints
         | 
| 222 217 | 
             
                        constraint = association.build_join_constraint(table, foreign_table)
         | 
| @@ -288,7 +283,7 @@ module Torque | |
| 288 283 | 
             
                          cte.is_a?(dependent_klass)
         | 
| 289 284 | 
             
                        end
         | 
| 290 285 |  | 
| 291 | 
            -
                        AuxiliaryStatement.build(dependent, base, options, bound_attributes)
         | 
| 286 | 
            +
                        AuxiliaryStatement.build(dependent, base, options, bound_attributes, join_sources)
         | 
| 292 287 | 
             
                      end
         | 
| 293 288 | 
             
                    end
         | 
| 294 289 |  | 
| @@ -2,10 +2,6 @@ module Torque | |
| 2 2 | 
             
              module PostgreSQL
         | 
| 3 3 | 
             
                include ActiveSupport::Configurable
         | 
| 4 4 |  | 
| 5 | 
            -
                # Stores a version check for compatibility purposes
         | 
| 6 | 
            -
                AR521 = (ActiveRecord.gem_version >= Gem::Version.new('5.2.1'))
         | 
| 7 | 
            -
                AR523 = (ActiveRecord.gem_version >= Gem::Version.new('5.2.3'))
         | 
| 8 | 
            -
             | 
| 9 5 | 
             
                # Use the same logger as the Active Record one
         | 
| 10 6 | 
             
                def self.logger
         | 
| 11 7 | 
             
                  ActiveRecord::Base.logger
         | 
| @@ -18,14 +18,7 @@ module Torque | |
| 18 18 | 
             
                    klass.find(self.id)
         | 
| 19 19 | 
             
                  end
         | 
| 20 20 |  | 
| 21 | 
            -
                  private
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                    def using_single_table_inheritance?(record) # :nodoc:
         | 
| 24 | 
            -
                      self.class.physically_inherited? || super
         | 
| 25 | 
            -
                    end
         | 
| 26 | 
            -
             | 
| 27 21 | 
             
                  module ClassMethods
         | 
| 28 | 
            -
             | 
| 29 22 | 
             
                    delegate :_auto_cast_attribute, :_record_class_attribute, to: ActiveRecord::Relation
         | 
| 30 23 |  | 
| 31 24 | 
             
                    # Get a full list of all attributes from a model and all its dependents
         | 
| @@ -101,9 +94,10 @@ module Torque | |
| 101 94 |  | 
| 102 95 | 
             
                    # Get the final decorated table, regardless of any special condition
         | 
| 103 96 | 
             
                    def decorated_table_name
         | 
| 104 | 
            -
                       | 
| 105 | 
            -
             | 
| 106 | 
            -
                        contained =  | 
| 97 | 
            +
                      parent_class = try(:module_parent) || try(:parent)
         | 
| 98 | 
            +
                      if parent_class < Base && !parent_class.abstract_class?
         | 
| 99 | 
            +
                        contained = parent_class.table_name
         | 
| 100 | 
            +
                        contained = contained.singularize if parent_class.pluralize_table_names
         | 
| 107 101 | 
             
                        contained += "_"
         | 
| 108 102 | 
             
                      end
         | 
| 109 103 |  | 
| @@ -144,17 +138,19 @@ module Torque | |
| 144 138 |  | 
| 145 139 | 
             
                    private
         | 
| 146 140 |  | 
| 147 | 
            -
                      def  | 
| 141 | 
            +
                      def instantiate_instance_of(klass, attributes, column_types = {}, &block)
         | 
| 142 | 
            +
                        return super unless klass.physically_inheritances?
         | 
| 143 | 
            +
             | 
| 148 144 | 
             
                        auto_cast = _auto_cast_attribute.to_s
         | 
| 149 145 | 
             
                        record_class = _record_class_attribute.to_s
         | 
| 146 | 
            +
                        return super unless attributes.key?(record_class) &&
         | 
| 147 | 
            +
                           attributes.delete(auto_cast) && attributes[record_class] != table_name
         | 
| 150 148 |  | 
| 151 | 
            -
                         | 
| 152 | 
            -
             | 
| 149 | 
            +
                        klass = casted_dependents[attributes[record_class]]
         | 
| 150 | 
            +
                        raise_unable_to_cast(attributes[record_class]) if klass.nil?
         | 
| 151 | 
            +
                        filter_attributes_for_cast(attributes, klass)
         | 
| 153 152 |  | 
| 154 | 
            -
                        klass  | 
| 155 | 
            -
                        raise_unable_to_cast(record[record_class]) if klass.nil?
         | 
| 156 | 
            -
                        filter_attributes_for_cast(record, klass)
         | 
| 157 | 
            -
                        klass
         | 
| 153 | 
            +
                        super(klass, attributes, column_types, &block)
         | 
| 158 154 | 
             
                      end
         | 
| 159 155 |  | 
| 160 156 | 
             
                      # Filter the record attributes to be loaded to not included those from
         | 
| @@ -12,28 +12,21 @@ module Torque | |
| 12 12 | 
             
                      false
         | 
| 13 13 | 
             
                    end
         | 
| 14 14 |  | 
| 15 | 
            -
                    #  | 
| 16 | 
            -
                     | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
                         | 
| 28 | 
            -
                        klass_scope       = klass_join_scope(table, predicate_builder)
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                        klass_scope.where!(build_id_constraint_between(table, foreign_table))
         | 
| 31 | 
            -
                        klass_scope.where!(type => foreign_klass.polymorphic_name) if type
         | 
| 32 | 
            -
                        klass_scope.where!(klass.send(:type_condition, table)) \
         | 
| 33 | 
            -
                          if klass.finder_needs_type_condition?
         | 
| 15 | 
            +
                    # Fix where the join_scope method is the one now responsible for
         | 
| 16 | 
            +
                    # building the join condition
         | 
| 17 | 
            +
                    def join_scope(table, foreign_table, foreign_klass)
         | 
| 18 | 
            +
                      return super unless connected_through_array?
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                      predicate_builder = predicate_builder(table)
         | 
| 21 | 
            +
                      scope_chain_items = join_scopes(table, predicate_builder)
         | 
| 22 | 
            +
                      klass_scope       = klass_join_scope(table, predicate_builder)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      klass_scope.where!(build_id_constraint_between(table, foreign_table))
         | 
| 25 | 
            +
                      klass_scope.where!(type => foreign_klass.polymorphic_name) if type
         | 
| 26 | 
            +
                      klass_scope.where!(klass.send(:type_condition, table)) \
         | 
| 27 | 
            +
                        if klass.finder_needs_type_condition?
         | 
| 34 28 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
                      end
         | 
| 29 | 
            +
                      scope_chain_items.inject(klass_scope, &:merge!)
         | 
| 37 30 | 
             
                    end
         | 
| 38 31 |  | 
| 39 32 | 
             
                    # Manually build the join constraint
         | 
| @@ -50,9 +43,9 @@ module Torque | |
| 50 43 | 
             
                      return klass_attr.eq(source_attr) unless connected_through_array?
         | 
| 51 44 |  | 
| 52 45 | 
             
                      # Klass and key are associated with the reflection Class
         | 
| 53 | 
            -
                      klass_type = klass.columns_hash[ | 
| 46 | 
            +
                      klass_type = klass.columns_hash[join_keys.key.to_s]
         | 
| 54 47 | 
             
                      # active_record and foreign_key are associated with the source Class
         | 
| 55 | 
            -
                      source_type = active_record.columns_hash[ | 
| 48 | 
            +
                      source_type = active_record.columns_hash[join_keys.foreign_key.to_s]
         | 
| 56 49 |  | 
| 57 50 | 
             
                      # If both are attributes but the left side is not an array, and the
         | 
| 58 51 | 
             
                      # right side is, use the ANY operation
         | 
| @@ -78,8 +71,8 @@ module Torque | |
| 78 71 | 
             
                    private
         | 
| 79 72 |  | 
| 80 73 | 
             
                      def build_id_constraint_between(table, foreign_table)
         | 
| 81 | 
            -
                        klass_attr  = table[ | 
| 82 | 
            -
                        source_attr = foreign_table[ | 
| 74 | 
            +
                        klass_attr  = table[join_keys.key.to_s]
         | 
| 75 | 
            +
                        source_attr = foreign_table[join_keys.foreign_key.to_s]
         | 
| 83 76 |  | 
| 84 77 | 
             
                        build_id_constraint(klass_attr, source_attr)
         | 
| 85 78 | 
             
                      end
         | 
| @@ -105,6 +98,7 @@ module Torque | |
| 105 98 | 
             
                      # returns either +nil+ or the inverse association name that it finds.
         | 
| 106 99 | 
             
                      def automatic_inverse_of
         | 
| 107 100 | 
             
                        return super unless connected_through_array?
         | 
| 101 | 
            +
             | 
| 108 102 | 
             
                        if can_find_inverse_of_automatically?(self)
         | 
| 109 103 | 
             
                          inverse_name = options[:as] || active_record.name.demodulize
         | 
| 110 104 | 
             
                          inverse_name = ActiveSupport::Inflector.underscore(inverse_name)
         | 
| @@ -52,11 +52,8 @@ module Torque | |
| 52 52 | 
             
                      when Array
         | 
| 53 53 | 
             
                        resolve_column(item, base)
         | 
| 54 54 | 
             
                      when Hash
         | 
| 55 | 
            -
                        raise ArgumentError,  | 
| 56 | 
            -
                        item.map  | 
| 57 | 
            -
                          other_list = [other_list] unless other_list.kind_of? Enumerable
         | 
| 58 | 
            -
                          resolve_column(other_list, key)
         | 
| 59 | 
            -
                        end
         | 
| 55 | 
            +
                        raise ArgumentError, 'Unsupported Hash for attributes on third level' if base
         | 
| 56 | 
            +
                        item.map { |key, other_list| resolve_column(Array.wrap(other_list), key) }
         | 
| 60 57 | 
             
                      else
         | 
| 61 58 | 
             
                        raise ArgumentError, "Unsupported argument type: #{value} (#{value.class})"
         | 
| 62 59 | 
             
                      end
         | 
| @@ -138,19 +135,17 @@ module Torque | |
| 138 135 | 
             
                ActiveRecord::Relation::SINGLE_VALUE_METHODS       += Relation::SINGLE_VALUE_METHODS
         | 
| 139 136 | 
             
                ActiveRecord::Relation::MULTI_VALUE_METHODS        += Relation::MULTI_VALUE_METHODS
         | 
| 140 137 | 
             
                ActiveRecord::Relation::VALUE_METHODS              += Relation::VALUE_METHODS
         | 
| 141 | 
            -
                ActiveRecord::QueryMethods::VALID_UNSCOPING_VALUES += [ | 
| 142 | 
            -
                   | 
| 138 | 
            +
                ActiveRecord::QueryMethods::VALID_UNSCOPING_VALUES += %i[cast_records itself_only
         | 
| 139 | 
            +
                  distinct_on auxiliary_statements]
         | 
| 143 140 |  | 
| 144 | 
            -
                 | 
| 145 | 
            -
                   | 
| 146 | 
            -
                    ActiveRecord::QueryMethods::DEFAULT_VALUES[value] | 
| 147 | 
            -
             | 
| 148 | 
            -
                  end
         | 
| 141 | 
            +
                Relation::SINGLE_VALUE_METHODS.each do |value|
         | 
| 142 | 
            +
                  ActiveRecord::QueryMethods::DEFAULT_VALUES[value] = nil \
         | 
| 143 | 
            +
                    if ActiveRecord::QueryMethods::DEFAULT_VALUES[value].nil?
         | 
| 144 | 
            +
                end
         | 
| 149 145 |  | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
                  end
         | 
| 146 | 
            +
                Relation::MULTI_VALUE_METHODS.each do |value|
         | 
| 147 | 
            +
                  ActiveRecord::QueryMethods::DEFAULT_VALUES[value] ||= \
         | 
| 148 | 
            +
                    ActiveRecord::QueryMethods::FROZEN_EMPTY_ARRAY
         | 
| 154 149 | 
             
                end
         | 
| 155 150 |  | 
| 156 151 | 
             
                $VERBOSE = warn_level
         | 
| @@ -33,30 +33,24 @@ module Torque | |
| 33 33 | 
             
                    # Get all auxiliary statements bound attributes and the base bound
         | 
| 34 34 | 
             
                    # attributes as well
         | 
| 35 35 | 
             
                    def bound_attributes
         | 
| 36 | 
            -
                       | 
| 37 | 
            -
             | 
| 38 | 
            -
                        visitor.accept(self.arel.ast, ::Arel::Collectors::Bind.new).value
         | 
| 39 | 
            -
                      else
         | 
| 40 | 
            -
                        return super unless self.auxiliary_statements_values.present?
         | 
| 41 | 
            -
                        bindings = self.auxiliary_statements_values.map(&:bound_attributes)
         | 
| 42 | 
            -
                        (bindings + super).flatten
         | 
| 43 | 
            -
                      end
         | 
| 36 | 
            +
                      visitor = ::Arel::Visitors::PostgreSQL.new(ActiveRecord::Base.connection)
         | 
| 37 | 
            +
                      visitor.accept(self.arel.ast, ::Arel::Collectors::Bind.new).value
         | 
| 44 38 | 
             
                    end
         | 
| 45 39 |  | 
| 46 40 | 
             
                    private
         | 
| 47 41 |  | 
| 48 42 | 
             
                      # Hook arel build to add the distinct on clause
         | 
| 49 43 | 
             
                      def build_arel(*)
         | 
| 50 | 
            -
                         | 
| 51 | 
            -
                         | 
| 52 | 
            -
                         | 
| 44 | 
            +
                        arel = super
         | 
| 45 | 
            +
                        subqueries = build_auxiliary_statements(arel)
         | 
| 46 | 
            +
                        subqueries.nil? ? arel : arel.with(subqueries)
         | 
| 53 47 | 
             
                      end
         | 
| 54 48 |  | 
| 55 49 | 
             
                      # Build all necessary data for auxiliary statements
         | 
| 56 | 
            -
                      def build_auxiliary_statements
         | 
| 57 | 
            -
                        return unless  | 
| 58 | 
            -
                         | 
| 59 | 
            -
                          klass.build(self)
         | 
| 50 | 
            +
                      def build_auxiliary_statements(arel)
         | 
| 51 | 
            +
                        return unless auxiliary_statements_values.present?
         | 
| 52 | 
            +
                        auxiliary_statements_values.map do |klass|
         | 
| 53 | 
            +
                          klass.build(self).tap { arel.join_sources.concat(klass.join_sources) }
         | 
| 60 54 | 
             
                        end
         | 
| 61 55 | 
             
                      end
         | 
| 62 56 |  | 
| @@ -33,7 +33,7 @@ module Torque | |
| 33 33 |  | 
| 34 34 | 
             
                      # Hook arel build to add the distinct on clause
         | 
| 35 35 | 
             
                      def build_arel(*)
         | 
| 36 | 
            -
                        arel =  | 
| 36 | 
            +
                        arel = super
         | 
| 37 37 | 
             
                        value = self.distinct_on_values
         | 
| 38 38 | 
             
                        arel.distinct_on(resolve_column(value)) if value.present?
         | 
| 39 39 | 
             
                        arel
         | 
| @@ -11,6 +11,7 @@ module Torque | |
| 11 11 | 
             
                    @data_sources_model_names = {}
         | 
| 12 12 | 
             
                    @inheritance_dependencies = {}
         | 
| 13 13 | 
             
                    @inheritance_associations = {}
         | 
| 14 | 
            +
                    @inheritance_loaded = false
         | 
| 14 15 | 
             
                  end
         | 
| 15 16 |  | 
| 16 17 | 
             
                  def initialize_dup(*) # :nodoc:
         | 
| @@ -22,16 +23,16 @@ module Torque | |
| 22 23 |  | 
| 23 24 | 
             
                  def encode_with(coder) # :nodoc:
         | 
| 24 25 | 
             
                    super
         | 
| 25 | 
            -
                    coder[ | 
| 26 | 
            -
                    coder[ | 
| 27 | 
            -
                    coder[ | 
| 26 | 
            +
                    coder['data_sources_model_names'] = @data_sources_model_names
         | 
| 27 | 
            +
                    coder['inheritance_dependencies'] = @inheritance_dependencies
         | 
| 28 | 
            +
                    coder['inheritance_associations'] = @inheritance_associations
         | 
| 28 29 | 
             
                  end
         | 
| 29 30 |  | 
| 30 31 | 
             
                  def init_with(coder) # :nodoc:
         | 
| 31 32 | 
             
                    super
         | 
| 32 | 
            -
                    @data_sources_model_names = coder[ | 
| 33 | 
            -
                    @inheritance_dependencies = coder[ | 
| 34 | 
            -
                    @inheritance_associations = coder[ | 
| 33 | 
            +
                    @data_sources_model_names = coder['data_sources_model_names']
         | 
| 34 | 
            +
                    @inheritance_dependencies = coder['inheritance_dependencies']
         | 
| 35 | 
            +
                    @inheritance_associations = coder['inheritance_associations']
         | 
| 35 36 | 
             
                  end
         | 
| 36 37 |  | 
| 37 38 | 
             
                  def add(table_name, *) # :nodoc:
         | 
| @@ -41,6 +42,7 @@ module Torque | |
| 41 42 | 
             
                    if @data_sources.key?(table_name)
         | 
| 42 43 | 
             
                      @inheritance_dependencies.clear
         | 
| 43 44 | 
             
                      @inheritance_associations.clear
         | 
| 45 | 
            +
                      @inheritance_loaded = false
         | 
| 44 46 | 
             
                    end
         | 
| 45 47 | 
             
                  end
         | 
| 46 48 |  | 
| @@ -49,6 +51,7 @@ module Torque | |
| 49 51 | 
             
                    @data_sources_model_names.clear
         | 
| 50 52 | 
             
                    @inheritance_dependencies.clear
         | 
| 51 53 | 
             
                    @inheritance_associations.clear
         | 
| 54 | 
            +
                    @inheritance_loaded = false
         | 
| 52 55 | 
             
                  end
         | 
| 53 56 |  | 
| 54 57 | 
             
                  def size # :nodoc:
         | 
| @@ -71,10 +74,12 @@ module Torque | |
| 71 74 | 
             
                      @inheritance_dependencies,
         | 
| 72 75 | 
             
                      @inheritance_associations,
         | 
| 73 76 | 
             
                      @data_sources_model_names,
         | 
| 77 | 
            +
                      @inheritance_loaded,
         | 
| 74 78 | 
             
                    ]
         | 
| 75 79 | 
             
                  end
         | 
| 76 80 |  | 
| 77 81 | 
             
                  def marshal_load(array) # :nodoc:
         | 
| 82 | 
            +
                    @inheritance_loaded = array.pop
         | 
| 78 83 | 
             
                    @data_sources_model_names = array.pop
         | 
| 79 84 | 
             
                    @inheritance_associations = array.pop
         | 
| 80 85 | 
             
                    @inheritance_dependencies = array.pop
         | 
| @@ -101,13 +106,13 @@ module Torque | |
| 101 106 | 
             
                  end
         | 
| 102 107 |  | 
| 103 108 | 
             
                  # Try to find a model based on a given table
         | 
| 104 | 
            -
                  def lookup_model(table_name,  | 
| 105 | 
            -
                     | 
| 109 | 
            +
                  def lookup_model(table_name, scoped_class = '')
         | 
| 110 | 
            +
                    scoped_class = scoped_class.name if scoped_class.is_a?(Class)
         | 
| 106 111 | 
             
                    return @data_sources_model_names[table_name] \
         | 
| 107 112 | 
             
                      if @data_sources_model_names.key?(table_name)
         | 
| 108 113 |  | 
| 109 114 | 
             
                    # Get all the possible scopes
         | 
| 110 | 
            -
                    scopes =  | 
| 115 | 
            +
                    scopes = scoped_class.scan(/(?:::)?[A-Z][a-z]+/)
         | 
| 111 116 | 
             
                    scopes.unshift('Object::')
         | 
| 112 117 |  | 
| 113 118 | 
             
                    # Consider the maximum namespaced possible model name
         | 
| @@ -164,14 +169,17 @@ module Torque | |
| 164 169 | 
             
                    # Reload information about tables inheritance and dependencies, uses a
         | 
| 165 170 | 
             
                    # cache to not perform additional checkes
         | 
| 166 171 | 
             
                    def reload_inheritance_data!
         | 
| 167 | 
            -
                      return if @ | 
| 172 | 
            +
                      return if @inheritance_loaded
         | 
| 168 173 | 
             
                      @inheritance_dependencies = connection.inherited_tables
         | 
| 169 174 | 
             
                      @inheritance_associations = generate_associations
         | 
| 175 | 
            +
                      @inheritance_loaded = true
         | 
| 170 176 | 
             
                    end
         | 
| 171 177 |  | 
| 172 178 | 
             
                    # Calculates the inverted dependency (association), where even indirect
         | 
| 173 179 | 
             
                    # inheritance comes up in the list
         | 
| 174 180 | 
             
                    def generate_associations
         | 
| 181 | 
            +
                      return {} if @inheritance_dependencies.empty?
         | 
| 182 | 
            +
             | 
| 175 183 | 
             
                      result = Hash.new{ |h, k| h[k] = [] }
         | 
| 176 184 | 
             
                      masters = @inheritance_dependencies.values.flatten.uniq
         | 
| 177 185 |  | 
| @@ -200,7 +208,7 @@ module Torque | |
| 200 208 | 
             
                      super
         | 
| 201 209 | 
             
                      @data_sources_model_names = Torque::PostgreSQL.config
         | 
| 202 210 | 
             
                        .irregular_models.slice(*@data_sources.keys).map do |table_name, model_name|
         | 
| 203 | 
            -
                        [table_name, model_name.constantize]
         | 
| 211 | 
            +
                        [table_name, (model_name.is_a?(Class) ? model_name : model_name.constantize)]
         | 
| 204 212 | 
             
                      end.to_h
         | 
| 205 213 | 
             
                    end
         | 
| 206 214 |  |