composite_primary_keys 13.0.1 → 13.0.2
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/History.rdoc +891 -888
 - data/README.rdoc +181 -181
 - data/Rakefile +37 -37
 - data/lib/composite_primary_keys/arel/sqlserver.rb +37 -37
 - data/lib/composite_primary_keys/arel/to_sql.rb +18 -18
 - data/lib/composite_primary_keys/associations/association.rb +23 -23
 - data/lib/composite_primary_keys/associations/collection_association.rb +31 -31
 - data/lib/composite_primary_keys/associations/foreign_association.rb +15 -15
 - data/lib/composite_primary_keys/associations/has_many_association.rb +35 -35
 - data/lib/composite_primary_keys/associations/{join_dependency.rb → join_association.rb} +1 -1
 - data/lib/composite_primary_keys/associations/through_association.rb +25 -25
 - data/lib/composite_primary_keys/autosave_association.rb +60 -60
 - data/lib/composite_primary_keys/composite_arrays.rb +86 -86
 - data/lib/composite_primary_keys/composite_relation.rb +29 -29
 - data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +10 -10
 - data/lib/composite_primary_keys/connection_adapters/postgresql/database_statements.rb +26 -26
 - data/lib/composite_primary_keys/counter_cache.rb +15 -15
 - data/lib/composite_primary_keys/fixtures.rb +21 -21
 - data/lib/composite_primary_keys/persistence.rb +82 -82
 - data/lib/composite_primary_keys/relation/calculations.rb +104 -104
 - data/lib/composite_primary_keys/sanitization.rb +42 -42
 - data/lib/composite_primary_keys/transactions.rb +34 -34
 - data/lib/composite_primary_keys/validations/uniqueness.rb +31 -31
 - data/lib/composite_primary_keys/version.rb +8 -8
 - data/lib/composite_primary_keys.rb +118 -118
 - data/scripts/console.rb +48 -48
 - data/scripts/txt2html +76 -76
 - data/scripts/txt2js +65 -65
 - data/tasks/databases/mysql.rake +40 -40
 - data/tasks/databases/oracle.rake +41 -41
 - data/tasks/databases/postgresql.rake +38 -38
 - data/tasks/databases/sqlite.rake +25 -25
 - data/tasks/databases/sqlserver.rake +43 -43
 - data/tasks/website.rake +18 -18
 - data/test/README_tests.rdoc +56 -56
 - data/test/abstract_unit.rb +114 -114
 - data/test/connections/connection_spec.rb +27 -27
 - data/test/connections/databases.example.yml +40 -40
 - data/test/connections/databases.yml +40 -39
 - data/test/fixtures/article.rb +10 -10
 - data/test/fixtures/articles.yml +7 -7
 - data/test/fixtures/capitol.rb +3 -3
 - data/test/fixtures/capitols.yml +16 -16
 - data/test/fixtures/comment.rb +5 -5
 - data/test/fixtures/comments.yml +17 -17
 - data/test/fixtures/department.rb +16 -16
 - data/test/fixtures/dorm.rb +2 -2
 - data/test/fixtures/dorms.yml +4 -4
 - data/test/fixtures/employee.rb +5 -5
 - data/test/fixtures/group.rb +2 -2
 - data/test/fixtures/groups.yml +6 -6
 - data/test/fixtures/membership.rb +8 -8
 - data/test/fixtures/membership_status.rb +2 -2
 - data/test/fixtures/membership_statuses.yml +16 -16
 - data/test/fixtures/memberships.yml +10 -10
 - data/test/fixtures/product.rb +9 -9
 - data/test/fixtures/product_tariff.rb +5 -5
 - data/test/fixtures/product_tariffs.yml +14 -14
 - data/test/fixtures/products.yml +11 -11
 - data/test/fixtures/reading.rb +4 -4
 - data/test/fixtures/readings.yml +10 -10
 - data/test/fixtures/reference_code.rb +7 -7
 - data/test/fixtures/reference_codes.yml +28 -28
 - data/test/fixtures/reference_type.rb +12 -12
 - data/test/fixtures/reference_types.yml +9 -9
 - data/test/fixtures/restaurant.rb +9 -9
 - data/test/fixtures/restaurants.yml +14 -14
 - data/test/fixtures/restaurants_suburb.rb +2 -2
 - data/test/fixtures/room.rb +11 -11
 - data/test/fixtures/room_assignment.rb +13 -13
 - data/test/fixtures/room_assignments.yml +24 -24
 - data/test/fixtures/room_attribute.rb +2 -2
 - data/test/fixtures/room_attribute_assignment.rb +4 -4
 - data/test/fixtures/room_attribute_assignments.yml +4 -4
 - data/test/fixtures/room_attributes.yml +2 -2
 - data/test/fixtures/rooms.yml +12 -12
 - data/test/fixtures/street.rb +2 -2
 - data/test/fixtures/student.rb +3 -3
 - data/test/fixtures/students.yml +15 -15
 - data/test/fixtures/suburb.rb +5 -5
 - data/test/fixtures/tariff.rb +5 -5
 - data/test/fixtures/tariffs.yml +14 -14
 - data/test/fixtures/topic_sources.yml +3 -3
 - data/test/fixtures/topics.yml +8 -8
 - data/test/fixtures/users.yml +10 -10
 - data/test/plugins/pagination.rb +405 -405
 - data/test/plugins/pagination_helper.rb +135 -135
 - data/test/test_associations.rb +372 -372
 - data/test/test_attribute_methods.rb +63 -63
 - data/test/test_callbacks.rb +99 -99
 - data/test/test_composite_arrays.rb +38 -38
 - data/test/test_counter_cache.rb +30 -30
 - data/test/test_dumpable.rb +15 -15
 - data/test/test_dup.rb +37 -37
 - data/test/test_equal.rb +26 -26
 - data/test/test_habtm.rb +141 -141
 - data/test/test_miscellaneous.rb +32 -32
 - data/test/test_optimistic.rb +18 -18
 - data/test/test_pagination.rb +35 -35
 - data/test/test_polymorphic.rb +43 -43
 - data/test/test_predicates.rb +59 -59
 - data/test/test_preload.rb +102 -102
 - data/test/test_santiago.rb +23 -23
 - data/test/test_touch.rb +23 -23
 - data/test/test_tutorial_example.rb +25 -25
 - data/test/test_validations.rb +13 -13
 - metadata +4 -4
 
| 
         @@ -1,82 +1,82 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module ActiveRecord
         
     | 
| 
       2 
     | 
    
         
            -
              module Persistence
         
     | 
| 
       3 
     | 
    
         
            -
                module ClassMethods
         
     | 
| 
       4 
     | 
    
         
            -
                  def delete(id_or_array)
         
     | 
| 
       5 
     | 
    
         
            -
                    # CPK
         
     | 
| 
       6 
     | 
    
         
            -
                    if self.composite?
         
     | 
| 
       7 
     | 
    
         
            -
                      id_or_array = if id_or_array.is_a?(CompositePrimaryKeys::CompositeKeys)
         
     | 
| 
       8 
     | 
    
         
            -
                                      [id_or_array]
         
     | 
| 
       9 
     | 
    
         
            -
                                    else
         
     | 
| 
       10 
     | 
    
         
            -
                                      Array(id_or_array)
         
     | 
| 
       11 
     | 
    
         
            -
                                    end
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
                      # Delete should return the number of deleted records
         
     | 
| 
       14 
     | 
    
         
            -
                      id_or_array.map do |id|
         
     | 
| 
       15 
     | 
    
         
            -
                        # Is the passed in id actually a record?
         
     | 
| 
       16 
     | 
    
         
            -
                        id = id.kind_of?(::ActiveRecord::Base) ? id.id : id
         
     | 
| 
       17 
     | 
    
         
            -
                        delete_by(cpk_id_predicate(self.arel_table, self.primary_key, id))
         
     | 
| 
       18 
     | 
    
         
            -
                      end.sum
         
     | 
| 
       19 
     | 
    
         
            -
                    else
         
     | 
| 
       20 
     | 
    
         
            -
                      delete_by(primary_key => id_or_array)
         
     | 
| 
       21 
     | 
    
         
            -
                    end
         
     | 
| 
       22 
     | 
    
         
            -
                  end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                  def _update_record(values, constraints) # :nodoc:
         
     | 
| 
       25 
     | 
    
         
            -
                    # CPK
         
     | 
| 
       26 
     | 
    
         
            -
                    if self.composite? && constraints[primary_key]
         
     | 
| 
       27 
     | 
    
         
            -
                      primary_key_values = constraints.delete(primary_key)
         
     | 
| 
       28 
     | 
    
         
            -
                      primary_key.each_with_index do |key, i|
         
     | 
| 
       29 
     | 
    
         
            -
                       constraints[key] = primary_key_values[i]
         
     | 
| 
       30 
     | 
    
         
            -
                      end
         
     | 
| 
       31 
     | 
    
         
            -
                    end
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                    constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                    um = arel_table.where(
         
     | 
| 
       36 
     | 
    
         
            -
                      constraints.reduce(&:and)
         
     | 
| 
       37 
     | 
    
         
            -
                    ).compile_update(_substitute_values(values), primary_key)
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
                    connection.update(um, "#{self} Update")
         
     | 
| 
       40 
     | 
    
         
            -
                  end
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                  def _delete_record(constraints) # :nodoc:
         
     | 
| 
       43 
     | 
    
         
            -
                    # CPK
         
     | 
| 
       44 
     | 
    
         
            -
                    if self.composite? && constraints[primary_key]
         
     | 
| 
       45 
     | 
    
         
            -
                      primary_key_values = constraints.delete(primary_key)
         
     | 
| 
       46 
     | 
    
         
            -
                      primary_key.each_with_index do |key, i|
         
     | 
| 
       47 
     | 
    
         
            -
                        constraints[key] = primary_key_values[i]
         
     | 
| 
       48 
     | 
    
         
            -
                      end
         
     | 
| 
       49 
     | 
    
         
            -
                    end
         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
                    constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
                    dm = Arel::DeleteManager.new
         
     | 
| 
       54 
     | 
    
         
            -
                    dm.from(arel_table)
         
     | 
| 
       55 
     | 
    
         
            -
                    dm.wheres = constraints
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                    connection.delete(dm, "#{self} Destroy")
         
     | 
| 
       58 
     | 
    
         
            -
                  end
         
     | 
| 
       59 
     | 
    
         
            -
                end
         
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                def _create_record(attribute_names = self.attribute_names)
         
     | 
| 
       62 
     | 
    
         
            -
                  attribute_names = attributes_for_create(attribute_names)
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
                  new_id = self.class._insert_record(
         
     | 
| 
       65 
     | 
    
         
            -
                      attributes_with_values(attribute_names)
         
     | 
| 
       66 
     | 
    
         
            -
                  )
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
                  # CPK
         
     | 
| 
       69 
     | 
    
         
            -
                  if self.composite?
         
     | 
| 
       70 
     | 
    
         
            -
                    self.id = self.id.zip(Array(new_id)).map {|id1, id2| id2.nil? ? id1 : id2}
         
     | 
| 
       71 
     | 
    
         
            -
                  else
         
     | 
| 
       72 
     | 
    
         
            -
                    self.id ||= new_id if self.class.primary_key
         
     | 
| 
       73 
     | 
    
         
            -
                  end
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
                  @new_record = false
         
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
                  yield(self) if block_given?
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                  id
         
     | 
| 
       80 
     | 
    
         
            -
                end
         
     | 
| 
       81 
     | 
    
         
            -
              end
         
     | 
| 
       82 
     | 
    
         
            -
            end
         
     | 
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Persistence
         
     | 
| 
      
 3 
     | 
    
         
            +
                module ClassMethods
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def delete(id_or_array)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    # CPK
         
     | 
| 
      
 6 
     | 
    
         
            +
                    if self.composite?
         
     | 
| 
      
 7 
     | 
    
         
            +
                      id_or_array = if id_or_array.is_a?(CompositePrimaryKeys::CompositeKeys)
         
     | 
| 
      
 8 
     | 
    
         
            +
                                      [id_or_array]
         
     | 
| 
      
 9 
     | 
    
         
            +
                                    else
         
     | 
| 
      
 10 
     | 
    
         
            +
                                      Array(id_or_array)
         
     | 
| 
      
 11 
     | 
    
         
            +
                                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                      # Delete should return the number of deleted records
         
     | 
| 
      
 14 
     | 
    
         
            +
                      id_or_array.map do |id|
         
     | 
| 
      
 15 
     | 
    
         
            +
                        # Is the passed in id actually a record?
         
     | 
| 
      
 16 
     | 
    
         
            +
                        id = id.kind_of?(::ActiveRecord::Base) ? id.id : id
         
     | 
| 
      
 17 
     | 
    
         
            +
                        delete_by(cpk_id_predicate(self.arel_table, self.primary_key, id))
         
     | 
| 
      
 18 
     | 
    
         
            +
                      end.sum
         
     | 
| 
      
 19 
     | 
    
         
            +
                    else
         
     | 
| 
      
 20 
     | 
    
         
            +
                      delete_by(primary_key => id_or_array)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def _update_record(values, constraints) # :nodoc:
         
     | 
| 
      
 25 
     | 
    
         
            +
                    # CPK
         
     | 
| 
      
 26 
     | 
    
         
            +
                    if self.composite? && constraints[primary_key]
         
     | 
| 
      
 27 
     | 
    
         
            +
                      primary_key_values = constraints.delete(primary_key)
         
     | 
| 
      
 28 
     | 
    
         
            +
                      primary_key.each_with_index do |key, i|
         
     | 
| 
      
 29 
     | 
    
         
            +
                       constraints[key] = primary_key_values[i]
         
     | 
| 
      
 30 
     | 
    
         
            +
                      end
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    um = arel_table.where(
         
     | 
| 
      
 36 
     | 
    
         
            +
                      constraints.reduce(&:and)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    ).compile_update(_substitute_values(values), primary_key)
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    connection.update(um, "#{self} Update")
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  def _delete_record(constraints) # :nodoc:
         
     | 
| 
      
 43 
     | 
    
         
            +
                    # CPK
         
     | 
| 
      
 44 
     | 
    
         
            +
                    if self.composite? && constraints[primary_key]
         
     | 
| 
      
 45 
     | 
    
         
            +
                      primary_key_values = constraints.delete(primary_key)
         
     | 
| 
      
 46 
     | 
    
         
            +
                      primary_key.each_with_index do |key, i|
         
     | 
| 
      
 47 
     | 
    
         
            +
                        constraints[key] = primary_key_values[i]
         
     | 
| 
      
 48 
     | 
    
         
            +
                      end
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    dm = Arel::DeleteManager.new
         
     | 
| 
      
 54 
     | 
    
         
            +
                    dm.from(arel_table)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    dm.wheres = constraints
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    connection.delete(dm, "#{self} Destroy")
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def _create_record(attribute_names = self.attribute_names)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  attribute_names = attributes_for_create(attribute_names)
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  new_id = self.class._insert_record(
         
     | 
| 
      
 65 
     | 
    
         
            +
                      attributes_with_values(attribute_names)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  )
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  # CPK
         
     | 
| 
      
 69 
     | 
    
         
            +
                  if self.composite?
         
     | 
| 
      
 70 
     | 
    
         
            +
                    self.id = self.id.zip(Array(new_id)).map {|id1, id2| id2.nil? ? id1 : id2}
         
     | 
| 
      
 71 
     | 
    
         
            +
                  else
         
     | 
| 
      
 72 
     | 
    
         
            +
                    self.id ||= new_id if self.class.primary_key
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  @new_record = false
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  yield(self) if block_given?
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  id
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,104 +1,104 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module CompositePrimaryKeys
         
     | 
| 
       2 
     | 
    
         
            -
              module ActiveRecord
         
     | 
| 
       3 
     | 
    
         
            -
                module Calculations
         
     | 
| 
       4 
     | 
    
         
            -
                  def aggregate_column(column_name)
         
     | 
| 
       5 
     | 
    
         
            -
                    # CPK
         
     | 
| 
       6 
     | 
    
         
            -
                    if column_name.kind_of?(Array)
         
     | 
| 
       7 
     | 
    
         
            -
                      # Note: Test don't seem to run this code?
         
     | 
| 
       8 
     | 
    
         
            -
                      column_name.map do |column|
         
     | 
| 
       9 
     | 
    
         
            -
                        @klass.arel_table[column]
         
     | 
| 
       10 
     | 
    
         
            -
                      end
         
     | 
| 
       11 
     | 
    
         
            -
                    elsif @klass.has_attribute?(column_name) || @klass.attribute_alias?(column_name)
         
     | 
| 
       12 
     | 
    
         
            -
                      @klass.arel_table[column_name]
         
     | 
| 
       13 
     | 
    
         
            -
                    else
         
     | 
| 
       14 
     | 
    
         
            -
                      Arel.sql(column_name == :all ? "*" : column_name.to_s)
         
     | 
| 
       15 
     | 
    
         
            -
                    end
         
     | 
| 
       16 
     | 
    
         
            -
                  end
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                  def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
         
     | 
| 
       19 
     | 
    
         
            -
                    column_alias = column_name
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                    # CPK
         
     | 
| 
       22 
     | 
    
         
            -
                    # if operation == "count" && (column_name == :all && distinct || has_limit_or_offset?)
         
     | 
| 
       23 
     | 
    
         
            -
                    #   # Shortcut when limit is zero.
         
     | 
| 
       24 
     | 
    
         
            -
                    #   return 0 if limit_value == 0
         
     | 
| 
       25 
     | 
    
         
            -
                    #
         
     | 
| 
       26 
     | 
    
         
            -
                    #   query_builder = build_count_subquery(spawn, column_name, distinct)
         
     | 
| 
       27 
     | 
    
         
            -
                    if operation == "count"
         
     | 
| 
       28 
     | 
    
         
            -
                      relation = unscope(:order)
         
     | 
| 
       29 
     | 
    
         
            -
                      query_builder = build_count_subquery(spawn, column_name, distinct)
         
     | 
| 
       30 
     | 
    
         
            -
                    else
         
     | 
| 
       31 
     | 
    
         
            -
                      # PostgreSQL doesn't like ORDER BY when there are no GROUP BY
         
     | 
| 
       32 
     | 
    
         
            -
                      relation = unscope(:order).distinct!(false)
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                      column = aggregate_column(column_name)
         
     | 
| 
       35 
     | 
    
         
            -
                      select_value = operation_over_aggregate_column(column, operation, distinct)
         
     | 
| 
       36 
     | 
    
         
            -
                      select_value.distinct = true if operation == "sum" && distinct
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
                      relation.select_values = [select_value]
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                      query_builder = relation.arel
         
     | 
| 
       41 
     | 
    
         
            -
                    end
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                    result = skip_query_cache_if_necessary { @klass.connection.select_all(query_builder) }
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                    type_cast_calculated_value(result.cast_values.first, operation) do |value|
         
     | 
| 
       46 
     | 
    
         
            -
                      type = column.try(:type_caster) ||
         
     | 
| 
       47 
     | 
    
         
            -
                        # CPK
         
     | 
| 
       48 
     | 
    
         
            -
                        # lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
         
     | 
| 
       49 
     | 
    
         
            -
                        lookup_cast_type_from_join_dependencies(column_name.to_s) || ::ActiveRecord::Type.default_value
         
     | 
| 
       50 
     | 
    
         
            -
                      type.deserialize(value)
         
     | 
| 
       51 
     | 
    
         
            -
                    end
         
     | 
| 
       52 
     | 
    
         
            -
                  end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                  def build_count_subquery(relation, column_name, distinct)
         
     | 
| 
       55 
     | 
    
         
            -
                    if column_name == :all
         
     | 
| 
       56 
     | 
    
         
            -
                      column_alias = Arel.star
         
     | 
| 
       57 
     | 
    
         
            -
                      # CPK
         
     | 
| 
       58 
     | 
    
         
            -
                      # relation.select_values = [ Arel.sql(FinderMethods::ONE_AS_ONE) ] unless distinct
         
     | 
| 
       59 
     | 
    
         
            -
                      relation.select_values = [ Arel.sql(::ActiveRecord::FinderMethods::ONE_AS_ONE) ] unless distinct
         
     | 
| 
       60 
     | 
    
         
            -
                    elsif column_name.is_a?(Array)
         
     | 
| 
       61 
     | 
    
         
            -
                      column_alias = Arel.star
         
     | 
| 
       62 
     | 
    
         
            -
                      relation.select_values = column_name.map do |column|
         
     | 
| 
       63 
     | 
    
         
            -
                        Arel::Attribute.new(@klass.unscoped.table, column)
         
     | 
| 
       64 
     | 
    
         
            -
                      end
         
     | 
| 
       65 
     | 
    
         
            -
                    else
         
     | 
| 
       66 
     | 
    
         
            -
                      column_alias = Arel.sql("count_column")
         
     | 
| 
       67 
     | 
    
         
            -
                      relation.select_values = [ aggregate_column(column_name).as(column_alias) ]
         
     | 
| 
       68 
     | 
    
         
            -
                    end
         
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
                    subquery_alias = Arel.sql("subquery_for_count")
         
     | 
| 
       71 
     | 
    
         
            -
                    select_value = operation_over_aggregate_column(column_alias, "count", false)
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
                    relation.build_subquery(subquery_alias, select_value)
         
     | 
| 
       74 
     | 
    
         
            -
                  end
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
                  def calculate(operation, column_name)
         
     | 
| 
       77 
     | 
    
         
            -
                    if has_include?(column_name)
         
     | 
| 
       78 
     | 
    
         
            -
                      relation = apply_join_dependency
         
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
                      if operation.to_s.downcase == "count"
         
     | 
| 
       81 
     | 
    
         
            -
                        unless distinct_value || distinct_select?(column_name || select_for_count)
         
     | 
| 
       82 
     | 
    
         
            -
                          relation.distinct!
         
     | 
| 
       83 
     | 
    
         
            -
                          # CPK
         
     | 
| 
       84 
     | 
    
         
            -
                          # relation.select_values = [ klass.primary_key || table[Arel.star] ]
         
     | 
| 
       85 
     | 
    
         
            -
                          if klass.primary_key.present? && klass.primary_key.is_a?(Array)
         
     | 
| 
       86 
     | 
    
         
            -
                            relation.select_values = klass.primary_key.map do |k|
         
     | 
| 
       87 
     | 
    
         
            -
                              "#{connection.quote_table_name(klass.table_name)}.#{connection.quote_column_name(k)}"
         
     | 
| 
       88 
     | 
    
         
            -
                            end
         
     | 
| 
       89 
     | 
    
         
            -
                          else
         
     | 
| 
       90 
     | 
    
         
            -
                            relation.select_values = [ klass.primary_key || table[Arel.star] ]
         
     | 
| 
       91 
     | 
    
         
            -
                          end
         
     | 
| 
       92 
     | 
    
         
            -
                        end
         
     | 
| 
       93 
     | 
    
         
            -
                        # PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
         
     | 
| 
       94 
     | 
    
         
            -
                        relation.order_values = [] if group_values.empty?
         
     | 
| 
       95 
     | 
    
         
            -
                      end
         
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
                      relation.calculate(operation, column_name)
         
     | 
| 
       98 
     | 
    
         
            -
                    else
         
     | 
| 
       99 
     | 
    
         
            -
                      perform_calculation(operation, column_name)
         
     | 
| 
       100 
     | 
    
         
            -
                    end
         
     | 
| 
       101 
     | 
    
         
            -
                  end
         
     | 
| 
       102 
     | 
    
         
            -
                end
         
     | 
| 
       103 
     | 
    
         
            -
              end
         
     | 
| 
       104 
     | 
    
         
            -
            end
         
     | 
| 
      
 1 
     | 
    
         
            +
            module CompositePrimaryKeys
         
     | 
| 
      
 2 
     | 
    
         
            +
              module ActiveRecord
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Calculations
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def aggregate_column(column_name)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    # CPK
         
     | 
| 
      
 6 
     | 
    
         
            +
                    if column_name.kind_of?(Array)
         
     | 
| 
      
 7 
     | 
    
         
            +
                      # Note: Test don't seem to run this code?
         
     | 
| 
      
 8 
     | 
    
         
            +
                      column_name.map do |column|
         
     | 
| 
      
 9 
     | 
    
         
            +
                        @klass.arel_table[column]
         
     | 
| 
      
 10 
     | 
    
         
            +
                      end
         
     | 
| 
      
 11 
     | 
    
         
            +
                    elsif @klass.has_attribute?(column_name) || @klass.attribute_alias?(column_name)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      @klass.arel_table[column_name]
         
     | 
| 
      
 13 
     | 
    
         
            +
                    else
         
     | 
| 
      
 14 
     | 
    
         
            +
                      Arel.sql(column_name == :all ? "*" : column_name.to_s)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
         
     | 
| 
      
 19 
     | 
    
         
            +
                    column_alias = column_name
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    # CPK
         
     | 
| 
      
 22 
     | 
    
         
            +
                    # if operation == "count" && (column_name == :all && distinct || has_limit_or_offset?)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    #   # Shortcut when limit is zero.
         
     | 
| 
      
 24 
     | 
    
         
            +
                    #   return 0 if limit_value == 0
         
     | 
| 
      
 25 
     | 
    
         
            +
                    #
         
     | 
| 
      
 26 
     | 
    
         
            +
                    #   query_builder = build_count_subquery(spawn, column_name, distinct)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    if operation == "count"
         
     | 
| 
      
 28 
     | 
    
         
            +
                      relation = unscope(:order)
         
     | 
| 
      
 29 
     | 
    
         
            +
                      query_builder = build_count_subquery(spawn, column_name, distinct)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    else
         
     | 
| 
      
 31 
     | 
    
         
            +
                      # PostgreSQL doesn't like ORDER BY when there are no GROUP BY
         
     | 
| 
      
 32 
     | 
    
         
            +
                      relation = unscope(:order).distinct!(false)
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                      column = aggregate_column(column_name)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      select_value = operation_over_aggregate_column(column, operation, distinct)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      select_value.distinct = true if operation == "sum" && distinct
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                      relation.select_values = [select_value]
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                      query_builder = relation.arel
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    result = skip_query_cache_if_necessary { @klass.connection.select_all(query_builder) }
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    type_cast_calculated_value(result.cast_values.first, operation) do |value|
         
     | 
| 
      
 46 
     | 
    
         
            +
                      type = column.try(:type_caster) ||
         
     | 
| 
      
 47 
     | 
    
         
            +
                        # CPK
         
     | 
| 
      
 48 
     | 
    
         
            +
                        # lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
         
     | 
| 
      
 49 
     | 
    
         
            +
                        lookup_cast_type_from_join_dependencies(column_name.to_s) || ::ActiveRecord::Type.default_value
         
     | 
| 
      
 50 
     | 
    
         
            +
                      type.deserialize(value)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    end
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  def build_count_subquery(relation, column_name, distinct)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    if column_name == :all
         
     | 
| 
      
 56 
     | 
    
         
            +
                      column_alias = Arel.star
         
     | 
| 
      
 57 
     | 
    
         
            +
                      # CPK
         
     | 
| 
      
 58 
     | 
    
         
            +
                      # relation.select_values = [ Arel.sql(FinderMethods::ONE_AS_ONE) ] unless distinct
         
     | 
| 
      
 59 
     | 
    
         
            +
                      relation.select_values = [ Arel.sql(::ActiveRecord::FinderMethods::ONE_AS_ONE) ] unless distinct
         
     | 
| 
      
 60 
     | 
    
         
            +
                    elsif column_name.is_a?(Array)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      column_alias = Arel.star
         
     | 
| 
      
 62 
     | 
    
         
            +
                      relation.select_values = column_name.map do |column|
         
     | 
| 
      
 63 
     | 
    
         
            +
                        Arel::Attribute.new(@klass.unscoped.table, column)
         
     | 
| 
      
 64 
     | 
    
         
            +
                      end
         
     | 
| 
      
 65 
     | 
    
         
            +
                    else
         
     | 
| 
      
 66 
     | 
    
         
            +
                      column_alias = Arel.sql("count_column")
         
     | 
| 
      
 67 
     | 
    
         
            +
                      relation.select_values = [ aggregate_column(column_name).as(column_alias) ]
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    subquery_alias = Arel.sql("subquery_for_count")
         
     | 
| 
      
 71 
     | 
    
         
            +
                    select_value = operation_over_aggregate_column(column_alias, "count", false)
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                    relation.build_subquery(subquery_alias, select_value)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  def calculate(operation, column_name)
         
     | 
| 
      
 77 
     | 
    
         
            +
                    if has_include?(column_name)
         
     | 
| 
      
 78 
     | 
    
         
            +
                      relation = apply_join_dependency
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                      if operation.to_s.downcase == "count"
         
     | 
| 
      
 81 
     | 
    
         
            +
                        unless distinct_value || distinct_select?(column_name || select_for_count)
         
     | 
| 
      
 82 
     | 
    
         
            +
                          relation.distinct!
         
     | 
| 
      
 83 
     | 
    
         
            +
                          # CPK
         
     | 
| 
      
 84 
     | 
    
         
            +
                          # relation.select_values = [ klass.primary_key || table[Arel.star] ]
         
     | 
| 
      
 85 
     | 
    
         
            +
                          if klass.primary_key.present? && klass.primary_key.is_a?(Array)
         
     | 
| 
      
 86 
     | 
    
         
            +
                            relation.select_values = klass.primary_key.map do |k|
         
     | 
| 
      
 87 
     | 
    
         
            +
                              "#{connection.quote_table_name(klass.table_name)}.#{connection.quote_column_name(k)}"
         
     | 
| 
      
 88 
     | 
    
         
            +
                            end
         
     | 
| 
      
 89 
     | 
    
         
            +
                          else
         
     | 
| 
      
 90 
     | 
    
         
            +
                            relation.select_values = [ klass.primary_key || table[Arel.star] ]
         
     | 
| 
      
 91 
     | 
    
         
            +
                          end
         
     | 
| 
      
 92 
     | 
    
         
            +
                        end
         
     | 
| 
      
 93 
     | 
    
         
            +
                        # PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
         
     | 
| 
      
 94 
     | 
    
         
            +
                        relation.order_values = [] if group_values.empty?
         
     | 
| 
      
 95 
     | 
    
         
            +
                      end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                      relation.calculate(operation, column_name)
         
     | 
| 
      
 98 
     | 
    
         
            +
                    else
         
     | 
| 
      
 99 
     | 
    
         
            +
                      perform_calculation(operation, column_name)
         
     | 
| 
      
 100 
     | 
    
         
            +
                    end
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,43 +1,43 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module ActiveRecord
         
     | 
| 
       2 
     | 
    
         
            -
              module Sanitization
         
     | 
| 
       3 
     | 
    
         
            -
                module ClassMethods
         
     | 
| 
       4 
     | 
    
         
            -
                #   def expand_hash_conditions_for_aggregates(attrs)
         
     | 
| 
       5 
     | 
    
         
            -
                #     expanded_attrs = {}
         
     | 
| 
       6 
     | 
    
         
            -
                #     attrs.each do |attr, value|
         
     | 
| 
       7 
     | 
    
         
            -
                #       # CPK
         
     | 
| 
       8 
     | 
    
         
            -
                #       # if aggregation = reflect_on_aggregation(attr.to_sym)
         
     | 
| 
       9 
     | 
    
         
            -
                #       if attr.is_a?(CompositePrimaryKeys::CompositeKeys)
         
     | 
| 
       10 
     | 
    
         
            -
                #         value = value.split('/') if value.is_a?(String)
         
     | 
| 
       11 
     | 
    
         
            -
                #         attr.each_with_index do |key,i|
         
     | 
| 
       12 
     | 
    
         
            -
                #           expanded_attrs[key] = value.respond_to?(:flatten) ? value.flatten[i] : value
         
     | 
| 
       13 
     | 
    
         
            -
                #         end
         
     | 
| 
       14 
     | 
    
         
            -
                #       elsif aggregation = reflect_on_aggregation(attr.to_sym)
         
     | 
| 
       15 
     | 
    
         
            -
                #         mapping = aggregation.mapping
         
     | 
| 
       16 
     | 
    
         
            -
                #         mapping.each do |field_attr, aggregate_attr|
         
     | 
| 
       17 
     | 
    
         
            -
                #           if mapping.size == 1 && !value.respond_to?(aggregate_attr)
         
     | 
| 
       18 
     | 
    
         
            -
                #             expanded_attrs[field_attr] = value
         
     | 
| 
       19 
     | 
    
         
            -
                #           else
         
     | 
| 
       20 
     | 
    
         
            -
                #             expanded_attrs[field_attr] = value.send(aggregate_attr)
         
     | 
| 
       21 
     | 
    
         
            -
                #           end
         
     | 
| 
       22 
     | 
    
         
            -
                #         end
         
     | 
| 
       23 
     | 
    
         
            -
                #       else
         
     | 
| 
       24 
     | 
    
         
            -
                #         expanded_attrs[attr] = value
         
     | 
| 
       25 
     | 
    
         
            -
                #       end
         
     | 
| 
       26 
     | 
    
         
            -
                #     end
         
     | 
| 
       27 
     | 
    
         
            -
                #     expanded_attrs
         
     | 
| 
       28 
     | 
    
         
            -
                #   end
         
     | 
| 
       29 
     | 
    
         
            -
                #
         
     | 
| 
       30 
     | 
    
         
            -
                #   def quoted_id
         
     | 
| 
       31 
     | 
    
         
            -
                #     # CPK
         
     | 
| 
       32 
     | 
    
         
            -
                #     # self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
         
     | 
| 
       33 
     | 
    
         
            -
                #     if self.composite?
         
     | 
| 
       34 
     | 
    
         
            -
                #       [self.class.primary_keys, ids].transpose.map { |attr_name,id|
         
     | 
| 
       35 
     | 
    
         
            -
                #         self.class.quote_value(@attributes[attr_name].value_for_database)
         
     | 
| 
       36 
     | 
    
         
            -
                #       }
         
     | 
| 
       37 
     | 
    
         
            -
                #     else
         
     | 
| 
       38 
     | 
    
         
            -
                #       self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
         
     | 
| 
       39 
     | 
    
         
            -
                #     end
         
     | 
| 
       40 
     | 
    
         
            -
                #   end
         
     | 
| 
       41 
     | 
    
         
            -
                end
         
     | 
| 
       42 
     | 
    
         
            -
              end
         
     | 
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Sanitization
         
     | 
| 
      
 3 
     | 
    
         
            +
                module ClassMethods
         
     | 
| 
      
 4 
     | 
    
         
            +
                #   def expand_hash_conditions_for_aggregates(attrs)
         
     | 
| 
      
 5 
     | 
    
         
            +
                #     expanded_attrs = {}
         
     | 
| 
      
 6 
     | 
    
         
            +
                #     attrs.each do |attr, value|
         
     | 
| 
      
 7 
     | 
    
         
            +
                #       # CPK
         
     | 
| 
      
 8 
     | 
    
         
            +
                #       # if aggregation = reflect_on_aggregation(attr.to_sym)
         
     | 
| 
      
 9 
     | 
    
         
            +
                #       if attr.is_a?(CompositePrimaryKeys::CompositeKeys)
         
     | 
| 
      
 10 
     | 
    
         
            +
                #         value = value.split('/') if value.is_a?(String)
         
     | 
| 
      
 11 
     | 
    
         
            +
                #         attr.each_with_index do |key,i|
         
     | 
| 
      
 12 
     | 
    
         
            +
                #           expanded_attrs[key] = value.respond_to?(:flatten) ? value.flatten[i] : value
         
     | 
| 
      
 13 
     | 
    
         
            +
                #         end
         
     | 
| 
      
 14 
     | 
    
         
            +
                #       elsif aggregation = reflect_on_aggregation(attr.to_sym)
         
     | 
| 
      
 15 
     | 
    
         
            +
                #         mapping = aggregation.mapping
         
     | 
| 
      
 16 
     | 
    
         
            +
                #         mapping.each do |field_attr, aggregate_attr|
         
     | 
| 
      
 17 
     | 
    
         
            +
                #           if mapping.size == 1 && !value.respond_to?(aggregate_attr)
         
     | 
| 
      
 18 
     | 
    
         
            +
                #             expanded_attrs[field_attr] = value
         
     | 
| 
      
 19 
     | 
    
         
            +
                #           else
         
     | 
| 
      
 20 
     | 
    
         
            +
                #             expanded_attrs[field_attr] = value.send(aggregate_attr)
         
     | 
| 
      
 21 
     | 
    
         
            +
                #           end
         
     | 
| 
      
 22 
     | 
    
         
            +
                #         end
         
     | 
| 
      
 23 
     | 
    
         
            +
                #       else
         
     | 
| 
      
 24 
     | 
    
         
            +
                #         expanded_attrs[attr] = value
         
     | 
| 
      
 25 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 26 
     | 
    
         
            +
                #     end
         
     | 
| 
      
 27 
     | 
    
         
            +
                #     expanded_attrs
         
     | 
| 
      
 28 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 29 
     | 
    
         
            +
                #
         
     | 
| 
      
 30 
     | 
    
         
            +
                #   def quoted_id
         
     | 
| 
      
 31 
     | 
    
         
            +
                #     # CPK
         
     | 
| 
      
 32 
     | 
    
         
            +
                #     # self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
         
     | 
| 
      
 33 
     | 
    
         
            +
                #     if self.composite?
         
     | 
| 
      
 34 
     | 
    
         
            +
                #       [self.class.primary_keys, ids].transpose.map { |attr_name,id|
         
     | 
| 
      
 35 
     | 
    
         
            +
                #         self.class.quote_value(@attributes[attr_name].value_for_database)
         
     | 
| 
      
 36 
     | 
    
         
            +
                #       }
         
     | 
| 
      
 37 
     | 
    
         
            +
                #     else
         
     | 
| 
      
 38 
     | 
    
         
            +
                #       self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
         
     | 
| 
      
 39 
     | 
    
         
            +
                #     end
         
     | 
| 
      
 40 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
       43 
43 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,34 +1,34 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module ActiveRecord
         
     | 
| 
       2 
     | 
    
         
            -
              module Transactions
         
     | 
| 
       3 
     | 
    
         
            -
                # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
         
     | 
| 
       4 
     | 
    
         
            -
                def restore_transaction_record_state(force_restore_state = false)
         
     | 
| 
       5 
     | 
    
         
            -
                  if restore_state = @_start_transaction_state
         
     | 
| 
       6 
     | 
    
         
            -
                    if force_restore_state || restore_state[:level] <= 1
         
     | 
| 
       7 
     | 
    
         
            -
                      @new_record = restore_state[:new_record]
         
     | 
| 
       8 
     | 
    
         
            -
                      @destroyed  = restore_state[:destroyed]
         
     | 
| 
       9 
     | 
    
         
            -
                      @attributes = restore_state[:attributes].map do |attr|
         
     | 
| 
       10 
     | 
    
         
            -
                        value = @attributes.fetch_value(attr.name)
         
     | 
| 
       11 
     | 
    
         
            -
                        attr = attr.with_value_from_user(value) if attr.value != value
         
     | 
| 
       12 
     | 
    
         
            -
                        attr
         
     | 
| 
       13 
     | 
    
         
            -
                      end
         
     | 
| 
       14 
     | 
    
         
            -
                      @mutations_from_database = nil
         
     | 
| 
       15 
     | 
    
         
            -
                      @mutations_before_last_save = nil
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                      # CPK
         
     | 
| 
       18 
     | 
    
         
            -
                      if self.composite?
         
     | 
| 
       19 
     | 
    
         
            -
                        values = @primary_key.map {|attribute| @attributes.fetch_value(attribute)}
         
     | 
| 
       20 
     | 
    
         
            -
                        restore_id = restore_state[:id]
         
     | 
| 
       21 
     | 
    
         
            -
                        if values != restore_id
         
     | 
| 
       22 
     | 
    
         
            -
                          @primary_key.each_with_index do |attribute, i|
         
     | 
| 
       23 
     | 
    
         
            -
                            @attributes.write_from_user(attribute, restore_id[i])
         
     | 
| 
       24 
     | 
    
         
            -
                          end
         
     | 
| 
       25 
     | 
    
         
            -
                        end
         
     | 
| 
       26 
     | 
    
         
            -
                      elsif @attributes.fetch_value(@primary_key) != restore_state[:id]
         
     | 
| 
       27 
     | 
    
         
            -
                        @attributes.write_from_user(@primary_key, restore_state[:id])
         
     | 
| 
       28 
     | 
    
         
            -
                      end
         
     | 
| 
       29 
     | 
    
         
            -
                      freeze if restore_state[:frozen?]
         
     | 
| 
       30 
     | 
    
         
            -
                    end
         
     | 
| 
       31 
     | 
    
         
            -
                  end
         
     | 
| 
       32 
     | 
    
         
            -
                end
         
     | 
| 
       33 
     | 
    
         
            -
              end
         
     | 
| 
       34 
     | 
    
         
            -
            end
         
     | 
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Transactions
         
     | 
| 
      
 3 
     | 
    
         
            +
                # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
         
     | 
| 
      
 4 
     | 
    
         
            +
                def restore_transaction_record_state(force_restore_state = false)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  if restore_state = @_start_transaction_state
         
     | 
| 
      
 6 
     | 
    
         
            +
                    if force_restore_state || restore_state[:level] <= 1
         
     | 
| 
      
 7 
     | 
    
         
            +
                      @new_record = restore_state[:new_record]
         
     | 
| 
      
 8 
     | 
    
         
            +
                      @destroyed  = restore_state[:destroyed]
         
     | 
| 
      
 9 
     | 
    
         
            +
                      @attributes = restore_state[:attributes].map do |attr|
         
     | 
| 
      
 10 
     | 
    
         
            +
                        value = @attributes.fetch_value(attr.name)
         
     | 
| 
      
 11 
     | 
    
         
            +
                        attr = attr.with_value_from_user(value) if attr.value != value
         
     | 
| 
      
 12 
     | 
    
         
            +
                        attr
         
     | 
| 
      
 13 
     | 
    
         
            +
                      end
         
     | 
| 
      
 14 
     | 
    
         
            +
                      @mutations_from_database = nil
         
     | 
| 
      
 15 
     | 
    
         
            +
                      @mutations_before_last_save = nil
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                      # CPK
         
     | 
| 
      
 18 
     | 
    
         
            +
                      if self.composite?
         
     | 
| 
      
 19 
     | 
    
         
            +
                        values = @primary_key.map {|attribute| @attributes.fetch_value(attribute)}
         
     | 
| 
      
 20 
     | 
    
         
            +
                        restore_id = restore_state[:id]
         
     | 
| 
      
 21 
     | 
    
         
            +
                        if values != restore_id
         
     | 
| 
      
 22 
     | 
    
         
            +
                          @primary_key.each_with_index do |attribute, i|
         
     | 
| 
      
 23 
     | 
    
         
            +
                            @attributes.write_from_user(attribute, restore_id[i])
         
     | 
| 
      
 24 
     | 
    
         
            +
                          end
         
     | 
| 
      
 25 
     | 
    
         
            +
                        end
         
     | 
| 
      
 26 
     | 
    
         
            +
                      elsif @attributes.fetch_value(@primary_key) != restore_state[:id]
         
     | 
| 
      
 27 
     | 
    
         
            +
                        @attributes.write_from_user(@primary_key, restore_state[:id])
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                      freeze if restore_state[:frozen?]
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,32 +1,32 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module ActiveRecord
         
     | 
| 
       2 
     | 
    
         
            -
              module Validations
         
     | 
| 
       3 
     | 
    
         
            -
                class UniquenessValidator
         
     | 
| 
       4 
     | 
    
         
            -
                  def validate_each(record, attribute, value)
         
     | 
| 
       5 
     | 
    
         
            -
                    finder_class = find_finder_class_for(record)
         
     | 
| 
       6 
     | 
    
         
            -
                    value = map_enum_attribute(finder_class, attribute, value)
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
                    relation = build_relation(finder_class, attribute, value)
         
     | 
| 
       9 
     | 
    
         
            -
                    if record.persisted?
         
     | 
| 
       10 
     | 
    
         
            -
                      # CPK
         
     | 
| 
       11 
     | 
    
         
            -
                      if finder_class.primary_key.is_a?(Array)
         
     | 
| 
       12 
     | 
    
         
            -
                        predicate = finder_class.cpk_id_predicate(finder_class.arel_table, finder_class.primary_key, record.id_in_database || record.id)
         
     | 
| 
       13 
     | 
    
         
            -
                        relation = relation.where.not(predicate)
         
     | 
| 
       14 
     | 
    
         
            -
                      elsif finder_class.primary_key
         
     | 
| 
       15 
     | 
    
         
            -
                        relation = relation.where.not(finder_class.primary_key => record.id_in_database)
         
     | 
| 
       16 
     | 
    
         
            -
                      else
         
     | 
| 
       17 
     | 
    
         
            -
                        raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
         
     | 
| 
       18 
     | 
    
         
            -
                      end
         
     | 
| 
       19 
     | 
    
         
            -
                    end
         
     | 
| 
       20 
     | 
    
         
            -
                    relation = scope_relation(record, relation)
         
     | 
| 
       21 
     | 
    
         
            -
                    relation = relation.merge(options[:conditions]) if options[:conditions]
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                    if relation.exists?
         
     | 
| 
       24 
     | 
    
         
            -
                      error_options = options.except(:case_sensitive, :scope, :conditions)
         
     | 
| 
       25 
     | 
    
         
            -
                      error_options[:value] = value
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                      record.errors.add(attribute, :taken, **error_options)
         
     | 
| 
       28 
     | 
    
         
            -
                    end
         
     | 
| 
       29 
     | 
    
         
            -
                  end
         
     | 
| 
       30 
     | 
    
         
            -
                end
         
     | 
| 
       31 
     | 
    
         
            -
              end
         
     | 
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Validations
         
     | 
| 
      
 3 
     | 
    
         
            +
                class UniquenessValidator
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def validate_each(record, attribute, value)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    finder_class = find_finder_class_for(record)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    value = map_enum_attribute(finder_class, attribute, value)
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                    relation = build_relation(finder_class, attribute, value)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    if record.persisted?
         
     | 
| 
      
 10 
     | 
    
         
            +
                      # CPK
         
     | 
| 
      
 11 
     | 
    
         
            +
                      if finder_class.primary_key.is_a?(Array)
         
     | 
| 
      
 12 
     | 
    
         
            +
                        predicate = finder_class.cpk_id_predicate(finder_class.arel_table, finder_class.primary_key, record.id_in_database || record.id)
         
     | 
| 
      
 13 
     | 
    
         
            +
                        relation = relation.where.not(predicate)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      elsif finder_class.primary_key
         
     | 
| 
      
 15 
     | 
    
         
            +
                        relation = relation.where.not(finder_class.primary_key => record.id_in_database)
         
     | 
| 
      
 16 
     | 
    
         
            +
                      else
         
     | 
| 
      
 17 
     | 
    
         
            +
                        raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
         
     | 
| 
      
 18 
     | 
    
         
            +
                      end
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    relation = scope_relation(record, relation)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    relation = relation.merge(options[:conditions]) if options[:conditions]
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    if relation.exists?
         
     | 
| 
      
 24 
     | 
    
         
            +
                      error_options = options.except(:case_sensitive, :scope, :conditions)
         
     | 
| 
      
 25 
     | 
    
         
            +
                      error_options[:value] = value
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                      record.errors.add(attribute, :taken, **error_options)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
       32 
32 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,8 +1,8 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module CompositePrimaryKeys
         
     | 
| 
       2 
     | 
    
         
            -
              module VERSION
         
     | 
| 
       3 
     | 
    
         
            -
                MAJOR = 13
         
     | 
| 
       4 
     | 
    
         
            -
                MINOR = 0
         
     | 
| 
       5 
     | 
    
         
            -
                TINY  =  
     | 
| 
       6 
     | 
    
         
            -
                STRING = [MAJOR, MINOR, TINY].join('.')
         
     | 
| 
       7 
     | 
    
         
            -
              end
         
     | 
| 
       8 
     | 
    
         
            -
            end
         
     | 
| 
      
 1 
     | 
    
         
            +
            module CompositePrimaryKeys
         
     | 
| 
      
 2 
     | 
    
         
            +
              module VERSION
         
     | 
| 
      
 3 
     | 
    
         
            +
                MAJOR = 13
         
     | 
| 
      
 4 
     | 
    
         
            +
                MINOR = 0
         
     | 
| 
      
 5 
     | 
    
         
            +
                TINY  = 2
         
     | 
| 
      
 6 
     | 
    
         
            +
                STRING = [MAJOR, MINOR, TINY].join('.')
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
            end
         
     |