activerecord 4.2.0 → 5.0.0
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.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +1537 -789
 - data/MIT-LICENSE +2 -2
 - data/README.rdoc +7 -8
 - data/examples/performance.rb +2 -3
 - data/examples/simple.rb +0 -1
 - data/lib/active_record/aggregations.rb +37 -23
 - data/lib/active_record/association_relation.rb +16 -3
 - data/lib/active_record/associations/alias_tracker.rb +19 -16
 - data/lib/active_record/associations/association.rb +23 -9
 - data/lib/active_record/associations/association_scope.rb +74 -102
 - data/lib/active_record/associations/belongs_to_association.rb +26 -29
 - data/lib/active_record/associations/builder/association.rb +28 -34
 - data/lib/active_record/associations/builder/belongs_to.rb +43 -18
 - data/lib/active_record/associations/builder/collection_association.rb +12 -20
 - data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +22 -15
 - data/lib/active_record/associations/builder/has_many.rb +4 -4
 - data/lib/active_record/associations/builder/has_one.rb +11 -6
 - data/lib/active_record/associations/builder/singular_association.rb +3 -10
 - data/lib/active_record/associations/collection_association.rb +61 -33
 - data/lib/active_record/associations/collection_proxy.rb +81 -35
 - data/lib/active_record/associations/foreign_association.rb +11 -0
 - data/lib/active_record/associations/has_many_association.rb +21 -57
 - data/lib/active_record/associations/has_many_through_association.rb +15 -45
 - data/lib/active_record/associations/has_one_association.rb +13 -5
 - data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
 - data/lib/active_record/associations/join_dependency.rb +37 -21
 - data/lib/active_record/associations/preloader/association.rb +51 -53
 - data/lib/active_record/associations/preloader/collection_association.rb +0 -6
 - data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
 - data/lib/active_record/associations/preloader/has_one.rb +0 -8
 - data/lib/active_record/associations/preloader/through_association.rb +27 -14
 - data/lib/active_record/associations/preloader.rb +18 -8
 - data/lib/active_record/associations/singular_association.rb +8 -8
 - data/lib/active_record/associations/through_association.rb +22 -9
 - data/lib/active_record/associations.rb +321 -212
 - data/lib/active_record/attribute/user_provided_default.rb +28 -0
 - data/lib/active_record/attribute.rb +79 -15
 - data/lib/active_record/attribute_assignment.rb +20 -141
 - data/lib/active_record/attribute_decorators.rb +6 -5
 - data/lib/active_record/attribute_methods/before_type_cast.rb +6 -1
 - data/lib/active_record/attribute_methods/dirty.rb +51 -81
 - data/lib/active_record/attribute_methods/primary_key.rb +2 -2
 - data/lib/active_record/attribute_methods/query.rb +2 -2
 - data/lib/active_record/attribute_methods/read.rb +31 -59
 - data/lib/active_record/attribute_methods/serialization.rb +13 -16
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -14
 - data/lib/active_record/attribute_methods/write.rb +14 -38
 - data/lib/active_record/attribute_methods.rb +70 -45
 - data/lib/active_record/attribute_mutation_tracker.rb +70 -0
 - data/lib/active_record/attribute_set/builder.rb +37 -15
 - data/lib/active_record/attribute_set.rb +34 -3
 - data/lib/active_record/attributes.rb +199 -73
 - data/lib/active_record/autosave_association.rb +73 -25
 - data/lib/active_record/base.rb +35 -27
 - data/lib/active_record/callbacks.rb +39 -43
 - data/lib/active_record/coders/json.rb +1 -1
 - data/lib/active_record/coders/yaml_column.rb +20 -8
 - data/lib/active_record/collection_cache_key.rb +40 -0
 - data/lib/active_record/connection_adapters/abstract/connection_pool.rb +457 -181
 - data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
 - data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -59
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
 - data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
 - data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -4
 - data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
 - data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +246 -185
 - data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +438 -136
 - data/lib/active_record/connection_adapters/abstract/transaction.rb +53 -40
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -66
 - data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +429 -335
 - data/lib/active_record/connection_adapters/column.rb +28 -43
 - data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
 - data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
 - data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
 - data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
 - data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
 - data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
 - data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
 - data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
 - data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
 - data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -177
 - data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
 - data/lib/active_record/connection_adapters/postgresql/database_statements.rb +11 -73
 - data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
 - data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -13
 - data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
 - data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
 - data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
 - data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
 - data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
 - data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +17 -5
 - data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
 - data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
 - data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
 - data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
 - data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
 - data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +248 -154
 - data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +258 -170
 - data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
 - data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
 - data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
 - data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
 - data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
 - data/lib/active_record/connection_adapters/sqlite3_adapter.rb +150 -209
 - data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
 - data/lib/active_record/connection_handling.rb +38 -15
 - data/lib/active_record/core.rb +109 -114
 - data/lib/active_record/counter_cache.rb +14 -25
 - data/lib/active_record/dynamic_matchers.rb +1 -20
 - data/lib/active_record/enum.rb +115 -79
 - data/lib/active_record/errors.rb +88 -48
 - data/lib/active_record/explain_registry.rb +1 -1
 - data/lib/active_record/explain_subscriber.rb +2 -2
 - data/lib/active_record/fixture_set/file.rb +26 -5
 - data/lib/active_record/fixtures.rb +84 -46
 - data/lib/active_record/gem_version.rb +2 -2
 - data/lib/active_record/inheritance.rb +32 -40
 - data/lib/active_record/integration.rb +4 -4
 - data/lib/active_record/internal_metadata.rb +56 -0
 - data/lib/active_record/legacy_yaml_adapter.rb +46 -0
 - data/lib/active_record/locale/en.yml +3 -2
 - data/lib/active_record/locking/optimistic.rb +27 -25
 - data/lib/active_record/locking/pessimistic.rb +1 -1
 - data/lib/active_record/log_subscriber.rb +43 -21
 - data/lib/active_record/migration/command_recorder.rb +59 -18
 - data/lib/active_record/migration/compatibility.rb +126 -0
 - data/lib/active_record/migration.rb +372 -114
 - data/lib/active_record/model_schema.rb +128 -38
 - data/lib/active_record/nested_attributes.rb +71 -32
 - data/lib/active_record/no_touching.rb +1 -1
 - data/lib/active_record/null_relation.rb +16 -8
 - data/lib/active_record/persistence.rb +124 -80
 - data/lib/active_record/query_cache.rb +15 -18
 - data/lib/active_record/querying.rb +10 -9
 - data/lib/active_record/railtie.rb +28 -19
 - data/lib/active_record/railties/controller_runtime.rb +1 -1
 - data/lib/active_record/railties/databases.rake +67 -51
 - data/lib/active_record/readonly_attributes.rb +1 -1
 - data/lib/active_record/reflection.rb +318 -139
 - data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
 - data/lib/active_record/relation/batches.rb +139 -34
 - data/lib/active_record/relation/calculations.rb +80 -102
 - data/lib/active_record/relation/delegation.rb +7 -20
 - data/lib/active_record/relation/finder_methods.rb +167 -97
 - data/lib/active_record/relation/from_clause.rb +32 -0
 - data/lib/active_record/relation/merger.rb +38 -41
 - data/lib/active_record/relation/predicate_builder/array_handler.rb +12 -16
 - data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
 - data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
 - data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
 - data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
 - data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
 - data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
 - data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
 - data/lib/active_record/relation/predicate_builder.rb +124 -82
 - data/lib/active_record/relation/query_attribute.rb +19 -0
 - data/lib/active_record/relation/query_methods.rb +323 -257
 - data/lib/active_record/relation/record_fetch_warning.rb +49 -0
 - data/lib/active_record/relation/spawn_methods.rb +11 -10
 - data/lib/active_record/relation/where_clause.rb +174 -0
 - data/lib/active_record/relation/where_clause_factory.rb +38 -0
 - data/lib/active_record/relation.rb +176 -115
 - data/lib/active_record/result.rb +4 -3
 - data/lib/active_record/runtime_registry.rb +1 -1
 - data/lib/active_record/sanitization.rb +95 -66
 - data/lib/active_record/schema.rb +26 -22
 - data/lib/active_record/schema_dumper.rb +62 -38
 - data/lib/active_record/schema_migration.rb +11 -17
 - data/lib/active_record/scoping/default.rb +24 -9
 - data/lib/active_record/scoping/named.rb +49 -28
 - data/lib/active_record/scoping.rb +32 -15
 - data/lib/active_record/secure_token.rb +38 -0
 - data/lib/active_record/serialization.rb +2 -4
 - data/lib/active_record/statement_cache.rb +16 -14
 - data/lib/active_record/store.rb +8 -3
 - data/lib/active_record/suppressor.rb +58 -0
 - data/lib/active_record/table_metadata.rb +68 -0
 - data/lib/active_record/tasks/database_tasks.rb +59 -42
 - data/lib/active_record/tasks/mysql_database_tasks.rb +32 -26
 - data/lib/active_record/tasks/postgresql_database_tasks.rb +29 -9
 - data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
 - data/lib/active_record/timestamp.rb +20 -9
 - data/lib/active_record/touch_later.rb +58 -0
 - data/lib/active_record/transactions.rb +159 -67
 - data/lib/active_record/type/adapter_specific_registry.rb +130 -0
 - data/lib/active_record/type/date.rb +2 -41
 - data/lib/active_record/type/date_time.rb +2 -38
 - data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
 - data/lib/active_record/type/internal/abstract_json.rb +29 -0
 - data/lib/active_record/type/internal/timezone.rb +15 -0
 - data/lib/active_record/type/serialized.rb +21 -14
 - data/lib/active_record/type/time.rb +10 -16
 - data/lib/active_record/type/type_map.rb +4 -4
 - data/lib/active_record/type.rb +66 -17
 - data/lib/active_record/type_caster/connection.rb +29 -0
 - data/lib/active_record/type_caster/map.rb +19 -0
 - data/lib/active_record/type_caster.rb +7 -0
 - data/lib/active_record/validations/absence.rb +23 -0
 - data/lib/active_record/validations/associated.rb +10 -3
 - data/lib/active_record/validations/length.rb +24 -0
 - data/lib/active_record/validations/presence.rb +11 -12
 - data/lib/active_record/validations/uniqueness.rb +29 -18
 - data/lib/active_record/validations.rb +33 -32
 - data/lib/active_record.rb +9 -2
 - data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
 - data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -6
 - data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -7
 - data/lib/rails/generators/active_record/migration.rb +7 -0
 - data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
 - data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
 - data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
 - metadata +60 -34
 - data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
 - data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
 - data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
 - data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
 - data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
 - data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
 - data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
 - data/lib/active_record/serializers/xml_serializer.rb +0 -193
 - data/lib/active_record/type/big_integer.rb +0 -13
 - data/lib/active_record/type/binary.rb +0 -50
 - data/lib/active_record/type/boolean.rb +0 -30
 - data/lib/active_record/type/decimal.rb +0 -40
 - data/lib/active_record/type/decimal_without_scale.rb +0 -11
 - data/lib/active_record/type/decorator.rb +0 -14
 - data/lib/active_record/type/float.rb +0 -19
 - data/lib/active_record/type/integer.rb +0 -55
 - data/lib/active_record/type/mutable.rb +0 -16
 - data/lib/active_record/type/numeric.rb +0 -36
 - data/lib/active_record/type/string.rb +0 -36
 - data/lib/active_record/type/text.rb +0 -11
 - data/lib/active_record/type/time_value.rb +0 -38
 - data/lib/active_record/type/unsigned_integer.rb +0 -15
 - data/lib/active_record/type/value.rb +0 -101
 
| 
         @@ -28,15 +28,21 @@ module ActiveRecord 
     | 
|
| 
       28 
28 
     | 
    
         
             
                  # Implements the reader method, e.g. foo.items for Foo.has_many :items
         
     | 
| 
       29 
29 
     | 
    
         
             
                  def reader(force_reload = false)
         
     | 
| 
       30 
30 
     | 
    
         
             
                    if force_reload
         
     | 
| 
      
 31 
     | 
    
         
            +
                      ActiveSupport::Deprecation.warn(<<-MSG.squish)
         
     | 
| 
      
 32 
     | 
    
         
            +
                        Passing an argument to force an association to reload is now
         
     | 
| 
      
 33 
     | 
    
         
            +
                        deprecated and will be removed in Rails 5.1. Please call `reload`
         
     | 
| 
      
 34 
     | 
    
         
            +
                        on the result collection proxy instead.
         
     | 
| 
      
 35 
     | 
    
         
            +
                      MSG
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
       31 
37 
     | 
    
         
             
                      klass.uncached { reload }
         
     | 
| 
       32 
38 
     | 
    
         
             
                    elsif stale_target?
         
     | 
| 
       33 
39 
     | 
    
         
             
                      reload
         
     | 
| 
       34 
40 
     | 
    
         
             
                    end
         
     | 
| 
       35 
41 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                    if  
     | 
| 
      
 42 
     | 
    
         
            +
                    if null_scope?
         
     | 
| 
       37 
43 
     | 
    
         
             
                      # Cache the proxy separately before the owner has an id
         
     | 
| 
       38 
44 
     | 
    
         
             
                      # or else a post-save proxy will still lack the id
         
     | 
| 
       39 
     | 
    
         
            -
                      @ 
     | 
| 
      
 45 
     | 
    
         
            +
                      @null_proxy ||= CollectionProxy.create(klass, self)
         
     | 
| 
       40 
46 
     | 
    
         
             
                    else
         
     | 
| 
       41 
47 
     | 
    
         
             
                      @proxy ||= CollectionProxy.create(klass, self)
         
     | 
| 
       42 
48 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -54,17 +60,22 @@ module ActiveRecord 
     | 
|
| 
       54 
60 
     | 
    
         
             
                        record.send(reflection.association_primary_key)
         
     | 
| 
       55 
61 
     | 
    
         
             
                      end
         
     | 
| 
       56 
62 
     | 
    
         
             
                    else
         
     | 
| 
       57 
     | 
    
         
            -
                       
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
      
 63 
     | 
    
         
            +
                      @association_ids ||= (
         
     | 
| 
      
 64 
     | 
    
         
            +
                        column = "#{reflection.quoted_table_name}.#{reflection.association_primary_key}"
         
     | 
| 
      
 65 
     | 
    
         
            +
                        scope.pluck(column)
         
     | 
| 
      
 66 
     | 
    
         
            +
                      )
         
     | 
| 
       59 
67 
     | 
    
         
             
                    end
         
     | 
| 
       60 
68 
     | 
    
         
             
                  end
         
     | 
| 
       61 
69 
     | 
    
         | 
| 
       62 
70 
     | 
    
         
             
                  # Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items
         
     | 
| 
       63 
71 
     | 
    
         
             
                  def ids_writer(ids)
         
     | 
| 
       64 
72 
     | 
    
         
             
                    pk_type = reflection.primary_key_type
         
     | 
| 
       65 
     | 
    
         
            -
                    ids = Array(ids).reject 
     | 
| 
       66 
     | 
    
         
            -
                    ids.map! { |i| pk_type. 
     | 
| 
       67 
     | 
    
         
            -
                     
     | 
| 
      
 73 
     | 
    
         
            +
                    ids = Array(ids).reject(&:blank?)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    ids.map! { |i| pk_type.cast(i) }
         
     | 
| 
      
 75 
     | 
    
         
            +
                    records = klass.where(reflection.association_primary_key => ids).index_by do |r|
         
     | 
| 
      
 76 
     | 
    
         
            +
                      r.send(reflection.association_primary_key)
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end.values_at(*ids)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    replace(records)
         
     | 
| 
       68 
79 
     | 
    
         
             
                  end
         
     | 
| 
       69 
80 
     | 
    
         | 
| 
       70 
81 
     | 
    
         
             
                  def reset
         
     | 
| 
         @@ -125,10 +136,28 @@ module ActiveRecord 
     | 
|
| 
       125 
136 
     | 
    
         
             
                    first_nth_or_last(:forty_two, *args)
         
     | 
| 
       126 
137 
     | 
    
         
             
                  end
         
     | 
| 
       127 
138 
     | 
    
         | 
| 
      
 139 
     | 
    
         
            +
                  def third_to_last(*args)
         
     | 
| 
      
 140 
     | 
    
         
            +
                    first_nth_or_last(:third_to_last, *args)
         
     | 
| 
      
 141 
     | 
    
         
            +
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                  def second_to_last(*args)
         
     | 
| 
      
 144 
     | 
    
         
            +
                    first_nth_or_last(:second_to_last, *args)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
       128 
147 
     | 
    
         
             
                  def last(*args)
         
     | 
| 
       129 
148 
     | 
    
         
             
                    first_nth_or_last(:last, *args)
         
     | 
| 
       130 
149 
     | 
    
         
             
                  end
         
     | 
| 
       131 
150 
     | 
    
         | 
| 
      
 151 
     | 
    
         
            +
                  def take(n = nil)
         
     | 
| 
      
 152 
     | 
    
         
            +
                    if loaded?
         
     | 
| 
      
 153 
     | 
    
         
            +
                      n ? target.take(n) : target.first
         
     | 
| 
      
 154 
     | 
    
         
            +
                    else
         
     | 
| 
      
 155 
     | 
    
         
            +
                      scope.take(n).tap do |record|
         
     | 
| 
      
 156 
     | 
    
         
            +
                        set_inverse_instance record if record.is_a? ActiveRecord::Base
         
     | 
| 
      
 157 
     | 
    
         
            +
                      end
         
     | 
| 
      
 158 
     | 
    
         
            +
                    end
         
     | 
| 
      
 159 
     | 
    
         
            +
                  end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
       132 
161 
     | 
    
         
             
                  def build(attributes = {}, &block)
         
     | 
| 
       133 
162 
     | 
    
         
             
                    if attributes.is_a?(Array)
         
     | 
| 
       134 
163 
     | 
    
         
             
                      attributes.collect { |attr| build(attr, &block) }
         
     | 
| 
         @@ -151,6 +180,7 @@ module ActiveRecord 
     | 
|
| 
       151 
180 
     | 
    
         
             
                  # be chained. Since << flattens its argument list and inserts each record,
         
     | 
| 
       152 
181 
     | 
    
         
             
                  # +push+ and +concat+ behave identically.
         
     | 
| 
       153 
182 
     | 
    
         
             
                  def concat(*records)
         
     | 
| 
      
 183 
     | 
    
         
            +
                    records = records.flatten
         
     | 
| 
       154 
184 
     | 
    
         
             
                    if owner.new_record?
         
     | 
| 
       155 
185 
     | 
    
         
             
                      load_target
         
     | 
| 
       156 
186 
     | 
    
         
             
                      concat_records(records)
         
     | 
| 
         @@ -218,11 +248,7 @@ module ActiveRecord 
     | 
|
| 
       218 
248 
     | 
    
         | 
| 
       219 
249 
     | 
    
         
             
                  # Count all records using SQL.  Construct options and pass them with
         
     | 
| 
       220 
250 
     | 
    
         
             
                  # scope to the target class's +count+.
         
     | 
| 
       221 
     | 
    
         
            -
                  def count(column_name = nil 
     | 
| 
       222 
     | 
    
         
            -
                    # TODO: Remove count_options argument as soon we remove support to
         
     | 
| 
       223 
     | 
    
         
            -
                    # activerecord-deprecated_finders.
         
     | 
| 
       224 
     | 
    
         
            -
                    column_name, count_options = nil, column_name if column_name.is_a?(Hash)
         
     | 
| 
       225 
     | 
    
         
            -
             
     | 
| 
      
 251 
     | 
    
         
            +
                  def count(column_name = nil)
         
     | 
| 
       226 
252 
     | 
    
         
             
                    relation = scope
         
     | 
| 
       227 
253 
     | 
    
         
             
                    if association_scope.distinct_value
         
     | 
| 
       228 
254 
     | 
    
         
             
                      # This is needed because 'SELECT count(DISTINCT *)..' is not valid SQL.
         
     | 
| 
         @@ -254,7 +280,7 @@ module ActiveRecord 
     | 
|
| 
       254 
280 
     | 
    
         
             
                    _options = records.extract_options!
         
     | 
| 
       255 
281 
     | 
    
         
             
                    dependent = _options[:dependent] || options[:dependent]
         
     | 
| 
       256 
282 
     | 
    
         | 
| 
       257 
     | 
    
         
            -
                    records = find(records) if records.any? { |record| record.kind_of?( 
     | 
| 
      
 283 
     | 
    
         
            +
                    records = find(records) if records.any? { |record| record.kind_of?(Integer) || record.kind_of?(String) }
         
     | 
| 
       258 
284 
     | 
    
         
             
                    delete_or_destroy(records, dependent)
         
     | 
| 
       259 
285 
     | 
    
         
             
                  end
         
     | 
| 
       260 
286 
     | 
    
         | 
| 
         @@ -265,7 +291,7 @@ module ActiveRecord 
     | 
|
| 
       265 
291 
     | 
    
         
             
                  # +:dependent+ option.
         
     | 
| 
       266 
292 
     | 
    
         
             
                  def destroy(*records)
         
     | 
| 
       267 
293 
     | 
    
         
             
                    return if records.empty?
         
     | 
| 
       268 
     | 
    
         
            -
                    records = find(records) if records.any? { |record| record.kind_of?( 
     | 
| 
      
 294 
     | 
    
         
            +
                    records = find(records) if records.any? { |record| record.kind_of?(Integer) || record.kind_of?(String) }
         
     | 
| 
       269 
295 
     | 
    
         
             
                    delete_or_destroy(records, :destroy)
         
     | 
| 
       270 
296 
     | 
    
         
             
                  end
         
     | 
| 
       271 
297 
     | 
    
         | 
| 
         @@ -289,7 +315,7 @@ module ActiveRecord 
     | 
|
| 
       289 
315 
     | 
    
         
             
                    elsif !loaded? && !association_scope.group_values.empty?
         
     | 
| 
       290 
316 
     | 
    
         
             
                      load_target.size
         
     | 
| 
       291 
317 
     | 
    
         
             
                    elsif !loaded? && !association_scope.distinct_value && target.is_a?(Array)
         
     | 
| 
       292 
     | 
    
         
            -
                      unsaved_records = target.select 
     | 
| 
      
 318 
     | 
    
         
            +
                      unsaved_records = target.select(&:new_record?)
         
     | 
| 
       293 
319 
     | 
    
         
             
                      unsaved_records.size + count_records
         
     | 
| 
       294 
320 
     | 
    
         
             
                    else
         
     | 
| 
       295 
321 
     | 
    
         
             
                      count_records
         
     | 
| 
         @@ -322,7 +348,8 @@ module ActiveRecord 
     | 
|
| 
       322 
348 
     | 
    
         
             
                  end
         
     | 
| 
       323 
349 
     | 
    
         | 
| 
       324 
350 
     | 
    
         
             
                  # Returns true if the collections is not empty.
         
     | 
| 
       325 
     | 
    
         
            -
                  #  
     | 
| 
      
 351 
     | 
    
         
            +
                  # If block given, loads all records and checks for one or more matches.
         
     | 
| 
      
 352 
     | 
    
         
            +
                  # Otherwise, equivalent to +!collection.empty?+.
         
     | 
| 
       326 
353 
     | 
    
         
             
                  def any?
         
     | 
| 
       327 
354 
     | 
    
         
             
                    if block_given?
         
     | 
| 
       328 
355 
     | 
    
         
             
                      load_target.any? { |*block_args| yield(*block_args) }
         
     | 
| 
         @@ -332,7 +359,8 @@ module ActiveRecord 
     | 
|
| 
       332 
359 
     | 
    
         
             
                  end
         
     | 
| 
       333 
360 
     | 
    
         | 
| 
       334 
361 
     | 
    
         
             
                  # Returns true if the collection has more than 1 record.
         
     | 
| 
       335 
     | 
    
         
            -
                  #  
     | 
| 
      
 362 
     | 
    
         
            +
                  # If block given, loads all records and checks for two or more matches.
         
     | 
| 
      
 363 
     | 
    
         
            +
                  # Otherwise, equivalent to +collection.size > 1+.
         
     | 
| 
       336 
364 
     | 
    
         
             
                  def many?
         
     | 
| 
       337 
365 
     | 
    
         
             
                    if block_given?
         
     | 
| 
       338 
366 
     | 
    
         
             
                      load_target.many? { |*block_args| yield(*block_args) }
         
     | 
| 
         @@ -361,6 +389,8 @@ module ActiveRecord 
     | 
|
| 
       361 
389 
     | 
    
         
             
                      replace_common_records_in_memory(other_array, original_target)
         
     | 
| 
       362 
390 
     | 
    
         
             
                      if other_array != original_target
         
     | 
| 
       363 
391 
     | 
    
         
             
                        transaction { replace_records(other_array, original_target) }
         
     | 
| 
      
 392 
     | 
    
         
            +
                      else
         
     | 
| 
      
 393 
     | 
    
         
            +
                        other_array
         
     | 
| 
       364 
394 
     | 
    
         
             
                      end
         
     | 
| 
       365 
395 
     | 
    
         
             
                    end
         
     | 
| 
       366 
396 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -395,12 +425,16 @@ module ActiveRecord 
     | 
|
| 
       395 
425 
     | 
    
         | 
| 
       396 
426 
     | 
    
         
             
                  def replace_on_target(record, index, skip_callbacks)
         
     | 
| 
       397 
427 
     | 
    
         
             
                    callback(:before_add, record) unless skip_callbacks
         
     | 
| 
      
 428 
     | 
    
         
            +
             
     | 
| 
      
 429 
     | 
    
         
            +
                    was_loaded = loaded?
         
     | 
| 
       398 
430 
     | 
    
         
             
                    yield(record) if block_given?
         
     | 
| 
       399 
431 
     | 
    
         | 
| 
       400 
     | 
    
         
            -
                     
     | 
| 
       401 
     | 
    
         
            -
                       
     | 
| 
       402 
     | 
    
         
            -
             
     | 
| 
       403 
     | 
    
         
            -
                       
     | 
| 
      
 432 
     | 
    
         
            +
                    unless !was_loaded && loaded?
         
     | 
| 
      
 433 
     | 
    
         
            +
                      if index
         
     | 
| 
      
 434 
     | 
    
         
            +
                        @target[index] = record
         
     | 
| 
      
 435 
     | 
    
         
            +
                      else
         
     | 
| 
      
 436 
     | 
    
         
            +
                        @target << record
         
     | 
| 
      
 437 
     | 
    
         
            +
                      end
         
     | 
| 
       404 
438 
     | 
    
         
             
                    end
         
     | 
| 
       405 
439 
     | 
    
         | 
| 
       406 
440 
     | 
    
         
             
                    callback(:after_add, record) unless skip_callbacks
         
     | 
| 
         @@ -421,13 +455,7 @@ module ActiveRecord 
     | 
|
| 
       421 
455 
     | 
    
         | 
| 
       422 
456 
     | 
    
         
             
                  private
         
     | 
| 
       423 
457 
     | 
    
         
             
                  def get_records
         
     | 
| 
       424 
     | 
    
         
            -
                    if  
     | 
| 
       425 
     | 
    
         
            -
                      scope.eager_loading? ||
         
     | 
| 
       426 
     | 
    
         
            -
                      klass.current_scope ||
         
     | 
| 
       427 
     | 
    
         
            -
                      klass.default_scopes.any?
         
     | 
| 
       428 
     | 
    
         
            -
             
     | 
| 
       429 
     | 
    
         
            -
                      return scope.to_a
         
     | 
| 
       430 
     | 
    
         
            -
                    end
         
     | 
| 
      
 458 
     | 
    
         
            +
                    return scope.to_a if skip_statement_cache?
         
     | 
| 
       431 
459 
     | 
    
         | 
| 
       432 
460 
     | 
    
         
             
                    conn = klass.connection
         
     | 
| 
       433 
461 
     | 
    
         
             
                    sc = reflection.association_scope_cache(conn, owner) do
         
     | 
| 
         @@ -506,7 +534,7 @@ module ActiveRecord 
     | 
|
| 
       506 
534 
     | 
    
         
             
                    def delete_or_destroy(records, method)
         
     | 
| 
       507 
535 
     | 
    
         
             
                      records = records.flatten
         
     | 
| 
       508 
536 
     | 
    
         
             
                      records.each { |record| raise_on_type_mismatch!(record) }
         
     | 
| 
       509 
     | 
    
         
            -
                      existing_records = records.reject 
     | 
| 
      
 537 
     | 
    
         
            +
                      existing_records = records.reject(&:new_record?)
         
     | 
| 
       510 
538 
     | 
    
         | 
| 
       511 
539 
     | 
    
         
             
                      if existing_records.empty?
         
     | 
| 
       512 
540 
     | 
    
         
             
                        remove_records(existing_records, records, method)
         
     | 
| 
         @@ -553,7 +581,7 @@ module ActiveRecord 
     | 
|
| 
       553 
581 
     | 
    
         
             
                    def concat_records(records, should_raise = false)
         
     | 
| 
       554 
582 
     | 
    
         
             
                      result = true
         
     | 
| 
       555 
583 
     | 
    
         | 
| 
       556 
     | 
    
         
            -
                      records. 
     | 
| 
      
 584 
     | 
    
         
            +
                      records.each do |record|
         
     | 
| 
       557 
585 
     | 
    
         
             
                        raise_on_type_mismatch!(record)
         
     | 
| 
       558 
586 
     | 
    
         
             
                        add_to_target(record) do |rec|
         
     | 
| 
       559 
587 
     | 
    
         
             
                          result &&= insert_record(rec, true, should_raise) unless owner.new_record?
         
     | 
| 
         @@ -597,8 +625,8 @@ module ActiveRecord 
     | 
|
| 
       597 
625 
     | 
    
         
             
                      if reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
         
     | 
| 
       598 
626 
     | 
    
         
             
                        assoc = owner.association(reflection.through_reflection.name)
         
     | 
| 
       599 
627 
     | 
    
         
             
                        assoc.reader.any? { |source|
         
     | 
| 
       600 
     | 
    
         
            -
                           
     | 
| 
       601 
     | 
    
         
            -
                           
     | 
| 
      
 628 
     | 
    
         
            +
                          target_reflection = source.send(reflection.source_reflection.name)
         
     | 
| 
      
 629 
     | 
    
         
            +
                          target_reflection.respond_to?(:include?) ? target_reflection.include?(record) : target_reflection == record
         
     | 
| 
       602 
630 
     | 
    
         
             
                        } || target.include?(record)
         
     | 
| 
       603 
631 
     | 
    
         
             
                      else
         
     | 
| 
       604 
632 
     | 
    
         
             
                        target.include?(record)
         
     | 
| 
         @@ -609,7 +637,7 @@ module ActiveRecord 
     | 
|
| 
       609 
637 
     | 
    
         
             
                    # specified, then #find scans the entire collection.
         
     | 
| 
       610 
638 
     | 
    
         
             
                    def find_by_scan(*args)
         
     | 
| 
       611 
639 
     | 
    
         
             
                      expects_array = args.first.kind_of?(Array)
         
     | 
| 
       612 
     | 
    
         
            -
                      ids           = args.flatten.compact.map 
     | 
| 
      
 640 
     | 
    
         
            +
                      ids           = args.flatten.compact.map(&:to_s).uniq
         
     | 
| 
       613 
641 
     | 
    
         | 
| 
       614 
642 
     | 
    
         
             
                      if ids.size == 1
         
     | 
| 
       615 
643 
     | 
    
         
             
                        id = ids.first
         
     | 
| 
         @@ -29,10 +29,11 @@ module ActiveRecord 
     | 
|
| 
       29 
29 
     | 
    
         
             
                # instantiation of the actual post records.
         
     | 
| 
       30 
30 
     | 
    
         
             
                class CollectionProxy < Relation
         
     | 
| 
       31 
31 
     | 
    
         
             
                  delegate(*(ActiveRecord::Calculations.public_instance_methods - [:count]), to: :scope)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  delegate :find_nth, to: :scope
         
     | 
| 
       32 
33 
     | 
    
         | 
| 
       33 
34 
     | 
    
         
             
                  def initialize(klass, association) #:nodoc:
         
     | 
| 
       34 
35 
     | 
    
         
             
                    @association = association
         
     | 
| 
       35 
     | 
    
         
            -
                    super klass, klass.arel_table
         
     | 
| 
      
 36 
     | 
    
         
            +
                    super klass, klass.arel_table, klass.predicate_builder
         
     | 
| 
       36 
37 
     | 
    
         
             
                    merge! association.scope(nullify: false)
         
     | 
| 
       37 
38 
     | 
    
         
             
                  end
         
     | 
| 
       38 
39 
     | 
    
         | 
| 
         @@ -111,7 +112,7 @@ module ActiveRecord 
     | 
|
| 
       111 
112 
     | 
    
         
             
                  end
         
     | 
| 
       112 
113 
     | 
    
         | 
| 
       113 
114 
     | 
    
         
             
                  # Finds an object in the collection responding to the +id+. Uses the same
         
     | 
| 
       114 
     | 
    
         
            -
                  # rules as  
     | 
| 
      
 115 
     | 
    
         
            +
                  # rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound
         
     | 
| 
       115 
116 
     | 
    
         
             
                  # error if the object cannot be found.
         
     | 
| 
       116 
117 
     | 
    
         
             
                  #
         
     | 
| 
       117 
118 
     | 
    
         
             
                  #   class Person < ActiveRecord::Base
         
     | 
| 
         @@ -126,7 +127,7 @@ module ActiveRecord 
     | 
|
| 
       126 
127 
     | 
    
         
             
                  #   #    ]
         
     | 
| 
       127 
128 
     | 
    
         
             
                  #
         
     | 
| 
       128 
129 
     | 
    
         
             
                  #   person.pets.find(1) # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
         
     | 
| 
       129 
     | 
    
         
            -
                  #   person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=4
         
     | 
| 
      
 130 
     | 
    
         
            +
                  #   person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=4
         
     | 
| 
       130 
131 
     | 
    
         
             
                  #
         
     | 
| 
       131 
132 
     | 
    
         
             
                  #   person.pets.find(2) { |pet| pet.name.downcase! }
         
     | 
| 
       132 
133 
     | 
    
         
             
                  #   # => #<Pet id: 2, name: "fancy-fancy", person_id: 1>
         
     | 
| 
         @@ -170,32 +171,42 @@ module ActiveRecord 
     | 
|
| 
       170 
171 
     | 
    
         
             
                    @association.first(*args)
         
     | 
| 
       171 
172 
     | 
    
         
             
                  end
         
     | 
| 
       172 
173 
     | 
    
         | 
| 
       173 
     | 
    
         
            -
                  # Same as  
     | 
| 
      
 174 
     | 
    
         
            +
                  # Same as #first except returns only the second record.
         
     | 
| 
       174 
175 
     | 
    
         
             
                  def second(*args)
         
     | 
| 
       175 
176 
     | 
    
         
             
                    @association.second(*args)
         
     | 
| 
       176 
177 
     | 
    
         
             
                  end
         
     | 
| 
       177 
178 
     | 
    
         | 
| 
       178 
     | 
    
         
            -
                  # Same as  
     | 
| 
      
 179 
     | 
    
         
            +
                  # Same as #first except returns only the third record.
         
     | 
| 
       179 
180 
     | 
    
         
             
                  def third(*args)
         
     | 
| 
       180 
181 
     | 
    
         
             
                    @association.third(*args)
         
     | 
| 
       181 
182 
     | 
    
         
             
                  end
         
     | 
| 
       182 
183 
     | 
    
         | 
| 
       183 
     | 
    
         
            -
                  # Same as  
     | 
| 
      
 184 
     | 
    
         
            +
                  # Same as #first except returns only the fourth record.
         
     | 
| 
       184 
185 
     | 
    
         
             
                  def fourth(*args)
         
     | 
| 
       185 
186 
     | 
    
         
             
                    @association.fourth(*args)
         
     | 
| 
       186 
187 
     | 
    
         
             
                  end
         
     | 
| 
       187 
188 
     | 
    
         | 
| 
       188 
     | 
    
         
            -
                  # Same as  
     | 
| 
      
 189 
     | 
    
         
            +
                  # Same as #first except returns only the fifth record.
         
     | 
| 
       189 
190 
     | 
    
         
             
                  def fifth(*args)
         
     | 
| 
       190 
191 
     | 
    
         
             
                    @association.fifth(*args)
         
     | 
| 
       191 
192 
     | 
    
         
             
                  end
         
     | 
| 
       192 
193 
     | 
    
         | 
| 
       193 
     | 
    
         
            -
                  # Same as  
     | 
| 
      
 194 
     | 
    
         
            +
                  # Same as #first except returns only the forty second record.
         
     | 
| 
       194 
195 
     | 
    
         
             
                  # Also known as accessing "the reddit".
         
     | 
| 
       195 
196 
     | 
    
         
             
                  def forty_two(*args)
         
     | 
| 
       196 
197 
     | 
    
         
             
                    @association.forty_two(*args)
         
     | 
| 
       197 
198 
     | 
    
         
             
                  end
         
     | 
| 
       198 
199 
     | 
    
         | 
| 
      
 200 
     | 
    
         
            +
                  # Same as #first except returns only the third-to-last record.
         
     | 
| 
      
 201 
     | 
    
         
            +
                  def third_to_last(*args)
         
     | 
| 
      
 202 
     | 
    
         
            +
                    @association.third_to_last(*args)
         
     | 
| 
      
 203 
     | 
    
         
            +
                  end
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
                  # Same as #first except returns only the second-to-last record.
         
     | 
| 
      
 206 
     | 
    
         
            +
                  def second_to_last(*args)
         
     | 
| 
      
 207 
     | 
    
         
            +
                    @association.second_to_last(*args)
         
     | 
| 
      
 208 
     | 
    
         
            +
                  end
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
       199 
210 
     | 
    
         
             
                  # Returns the last record, or the last +n+ records, from the collection.
         
     | 
| 
       200 
211 
     | 
    
         
             
                  # If the collection is empty, the first form returns +nil+, and the second
         
     | 
| 
       201 
212 
     | 
    
         
             
                  # form returns an empty array.
         
     | 
| 
         @@ -226,6 +237,35 @@ module ActiveRecord 
     | 
|
| 
       226 
237 
     | 
    
         
             
                    @association.last(*args)
         
     | 
| 
       227 
238 
     | 
    
         
             
                  end
         
     | 
| 
       228 
239 
     | 
    
         | 
| 
      
 240 
     | 
    
         
            +
                  # Gives a record (or N records if a parameter is supplied) from the collection
         
     | 
| 
      
 241 
     | 
    
         
            +
                  # using the same rules as <tt>ActiveRecord::Base.take</tt>.
         
     | 
| 
      
 242 
     | 
    
         
            +
                  #
         
     | 
| 
      
 243 
     | 
    
         
            +
                  #   class Person < ActiveRecord::Base
         
     | 
| 
      
 244 
     | 
    
         
            +
                  #     has_many :pets
         
     | 
| 
      
 245 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 246 
     | 
    
         
            +
                  #
         
     | 
| 
      
 247 
     | 
    
         
            +
                  #   person.pets
         
     | 
| 
      
 248 
     | 
    
         
            +
                  #   # => [
         
     | 
| 
      
 249 
     | 
    
         
            +
                  #   #       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
         
     | 
| 
      
 250 
     | 
    
         
            +
                  #   #       #<Pet id: 2, name: "Spook", person_id: 1>,
         
     | 
| 
      
 251 
     | 
    
         
            +
                  #   #       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
         
     | 
| 
      
 252 
     | 
    
         
            +
                  #   #    ]
         
     | 
| 
      
 253 
     | 
    
         
            +
                  #
         
     | 
| 
      
 254 
     | 
    
         
            +
                  #   person.pets.take # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
         
     | 
| 
      
 255 
     | 
    
         
            +
                  #
         
     | 
| 
      
 256 
     | 
    
         
            +
                  #   person.pets.take(2)
         
     | 
| 
      
 257 
     | 
    
         
            +
                  #   # => [
         
     | 
| 
      
 258 
     | 
    
         
            +
                  #   #      #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
         
     | 
| 
      
 259 
     | 
    
         
            +
                  #   #      #<Pet id: 2, name: "Spook", person_id: 1>
         
     | 
| 
      
 260 
     | 
    
         
            +
                  #   #    ]
         
     | 
| 
      
 261 
     | 
    
         
            +
                  #
         
     | 
| 
      
 262 
     | 
    
         
            +
                  #   another_person_without.pets         # => []
         
     | 
| 
      
 263 
     | 
    
         
            +
                  #   another_person_without.pets.take    # => nil
         
     | 
| 
      
 264 
     | 
    
         
            +
                  #   another_person_without.pets.take(2) # => []
         
     | 
| 
      
 265 
     | 
    
         
            +
                  def take(n = nil)
         
     | 
| 
      
 266 
     | 
    
         
            +
                    @association.take(n)
         
     | 
| 
      
 267 
     | 
    
         
            +
                  end
         
     | 
| 
      
 268 
     | 
    
         
            +
             
     | 
| 
       229 
269 
     | 
    
         
             
                  # Returns a new object of the collection type that has been instantiated
         
     | 
| 
       230 
270 
     | 
    
         
             
                  # with +attributes+ and linked to this object, but have not yet been saved.
         
     | 
| 
       231 
271 
     | 
    
         
             
                  # You can pass an array of attributes hashes, this will return an array
         
     | 
| 
         @@ -285,7 +325,7 @@ module ActiveRecord 
     | 
|
| 
       285 
325 
     | 
    
         
             
                    @association.create(attributes, &block)
         
     | 
| 
       286 
326 
     | 
    
         
             
                  end
         
     | 
| 
       287 
327 
     | 
    
         | 
| 
       288 
     | 
    
         
            -
                  # Like  
     | 
| 
      
 328 
     | 
    
         
            +
                  # Like #create, except that if the record is invalid, raises an exception.
         
     | 
| 
       289 
329 
     | 
    
         
             
                  #
         
     | 
| 
       290 
330 
     | 
    
         
             
                  #   class Person
         
     | 
| 
       291 
331 
     | 
    
         
             
                  #     has_many :pets
         
     | 
| 
         @@ -302,8 +342,8 @@ module ActiveRecord 
     | 
|
| 
       302 
342 
     | 
    
         
             
                  end
         
     | 
| 
       303 
343 
     | 
    
         | 
| 
       304 
344 
     | 
    
         
             
                  # Add one or more records to the collection by setting their foreign keys
         
     | 
| 
       305 
     | 
    
         
            -
                  # to the association's primary key. Since  
     | 
| 
       306 
     | 
    
         
            -
                  # inserts each record, +push+ and  
     | 
| 
      
 345 
     | 
    
         
            +
                  # to the association's primary key. Since #<< flattens its argument list and
         
     | 
| 
      
 346 
     | 
    
         
            +
                  # inserts each record, +push+ and #concat behave identically. Returns +self+
         
     | 
| 
       307 
347 
     | 
    
         
             
                  # so method calls may be chained.
         
     | 
| 
       308 
348 
     | 
    
         
             
                  #
         
     | 
| 
       309 
349 
     | 
    
         
             
                  #   class Person < ActiveRecord::Base
         
     | 
| 
         @@ -359,7 +399,7 @@ module ActiveRecord 
     | 
|
| 
       359 
399 
     | 
    
         
             
                  # specified by the +:dependent+ option. If no +:dependent+ option is given,
         
     | 
| 
       360 
400 
     | 
    
         
             
                  # then it will follow the default strategy.
         
     | 
| 
       361 
401 
     | 
    
         
             
                  #
         
     | 
| 
       362 
     | 
    
         
            -
                  # For  
     | 
| 
      
 402 
     | 
    
         
            +
                  # For <tt>has_many :through</tt> associations, the default deletion strategy is
         
     | 
| 
       363 
403 
     | 
    
         
             
                  # +:delete_all+.
         
     | 
| 
       364 
404 
     | 
    
         
             
                  #
         
     | 
| 
       365 
405 
     | 
    
         
             
                  # For +has_many+ associations, the default deletion strategy is +:nullify+.
         
     | 
| 
         @@ -394,7 +434,7 @@ module ActiveRecord 
     | 
|
| 
       394 
434 
     | 
    
         
             
                  #   #       #<Pet id: 3, name: "Choo-Choo", person_id: nil>
         
     | 
| 
       395 
435 
     | 
    
         
             
                  #   #    ]
         
     | 
| 
       396 
436 
     | 
    
         
             
                  #
         
     | 
| 
       397 
     | 
    
         
            -
                  # Both +has_many+ and  
     | 
| 
      
 437 
     | 
    
         
            +
                  # Both +has_many+ and <tt>has_many :through</tt> dependencies default to the
         
     | 
| 
       398 
438 
     | 
    
         
             
                  # +:delete_all+ strategy if the +:dependent+ option is set to +:destroy+.
         
     | 
| 
       399 
439 
     | 
    
         
             
                  # Records are not instantiated and callbacks will not be fired.
         
     | 
| 
       400 
440 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -413,7 +453,7 @@ module ActiveRecord 
     | 
|
| 
       413 
453 
     | 
    
         
             
                  #   person.pets.delete_all
         
     | 
| 
       414 
454 
     | 
    
         
             
                  #
         
     | 
| 
       415 
455 
     | 
    
         
             
                  #   Pet.find(1, 2, 3)
         
     | 
| 
       416 
     | 
    
         
            -
                  #   # => ActiveRecord::RecordNotFound
         
     | 
| 
      
 456 
     | 
    
         
            +
                  #   # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
         
     | 
| 
       417 
457 
     | 
    
         
             
                  #
         
     | 
| 
       418 
458 
     | 
    
         
             
                  # If it is set to <tt>:delete_all</tt>, all the objects are deleted
         
     | 
| 
       419 
459 
     | 
    
         
             
                  # *without* calling their +destroy+ method.
         
     | 
| 
         @@ -433,7 +473,7 @@ module ActiveRecord 
     | 
|
| 
       433 
473 
     | 
    
         
             
                  #   person.pets.delete_all
         
     | 
| 
       434 
474 
     | 
    
         
             
                  #
         
     | 
| 
       435 
475 
     | 
    
         
             
                  #   Pet.find(1, 2, 3)
         
     | 
| 
       436 
     | 
    
         
            -
                  #   # => ActiveRecord::RecordNotFound
         
     | 
| 
      
 476 
     | 
    
         
            +
                  #   # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
         
     | 
| 
       437 
477 
     | 
    
         
             
                  def delete_all(dependent = nil)
         
     | 
| 
       438 
478 
     | 
    
         
             
                    @association.delete_all(dependent)
         
     | 
| 
       439 
479 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -465,15 +505,16 @@ module ActiveRecord 
     | 
|
| 
       465 
505 
     | 
    
         
             
                    @association.destroy_all
         
     | 
| 
       466 
506 
     | 
    
         
             
                  end
         
     | 
| 
       467 
507 
     | 
    
         | 
| 
       468 
     | 
    
         
            -
                  # Deletes the +records+ supplied  
     | 
| 
       469 
     | 
    
         
            -
                  #  
     | 
| 
       470 
     | 
    
         
            -
                  #  
     | 
| 
      
 508 
     | 
    
         
            +
                  # Deletes the +records+ supplied from the collection according to the strategy
         
     | 
| 
      
 509 
     | 
    
         
            +
                  # specified by the +:dependent+ option. If no +:dependent+ option is given,
         
     | 
| 
      
 510 
     | 
    
         
            +
                  # then it will follow the default strategy. Returns an array with the
         
     | 
| 
       471 
511 
     | 
    
         
             
                  # deleted records.
         
     | 
| 
       472 
512 
     | 
    
         
             
                  #
         
     | 
| 
       473 
     | 
    
         
            -
                  #  
     | 
| 
       474 
     | 
    
         
            -
                  #  
     | 
| 
       475 
     | 
    
         
            -
                  # 
     | 
| 
       476 
     | 
    
         
            -
                  # strategy is  
     | 
| 
      
 513 
     | 
    
         
            +
                  # For <tt>has_many :through</tt> associations, the default deletion strategy is
         
     | 
| 
      
 514 
     | 
    
         
            +
                  # +:delete_all+.
         
     | 
| 
      
 515 
     | 
    
         
            +
                  #
         
     | 
| 
      
 516 
     | 
    
         
            +
                  # For +has_many+ associations, the default deletion strategy is +:nullify+.
         
     | 
| 
      
 517 
     | 
    
         
            +
                  # This sets the foreign keys to +NULL+.
         
     | 
| 
       477 
518 
     | 
    
         
             
                  #
         
     | 
| 
       478 
519 
     | 
    
         
             
                  #   class Person < ActiveRecord::Base
         
     | 
| 
       479 
520 
     | 
    
         
             
                  #     has_many :pets # dependent: :nullify option by default
         
     | 
| 
         @@ -526,7 +567,7 @@ module ActiveRecord 
     | 
|
| 
       526 
567 
     | 
    
         
             
                  #   # => [#<Pet id: 2, name: "Spook", person_id: 1>]
         
     | 
| 
       527 
568 
     | 
    
         
             
                  #
         
     | 
| 
       528 
569 
     | 
    
         
             
                  #   Pet.find(1, 3)
         
     | 
| 
       529 
     | 
    
         
            -
                  #   # => ActiveRecord::RecordNotFound: Couldn't find all Pets with  
     | 
| 
      
 570 
     | 
    
         
            +
                  #   # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 3)
         
     | 
| 
       530 
571 
     | 
    
         
             
                  #
         
     | 
| 
       531 
572 
     | 
    
         
             
                  # If it is set to <tt>:delete_all</tt>, all the +records+ are deleted
         
     | 
| 
       532 
573 
     | 
    
         
             
                  # *without* calling their +destroy+ method.
         
     | 
| 
         @@ -554,9 +595,9 @@ module ActiveRecord 
     | 
|
| 
       554 
595 
     | 
    
         
             
                  #   #    ]
         
     | 
| 
       555 
596 
     | 
    
         
             
                  #
         
     | 
| 
       556 
597 
     | 
    
         
             
                  #   Pet.find(1)
         
     | 
| 
       557 
     | 
    
         
            -
                  #   # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=1
         
     | 
| 
      
 598 
     | 
    
         
            +
                  #   # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=1
         
     | 
| 
       558 
599 
     | 
    
         
             
                  #
         
     | 
| 
       559 
     | 
    
         
            -
                  # You can pass + 
     | 
| 
      
 600 
     | 
    
         
            +
                  # You can pass +Integer+ or +String+ values, it finds the records
         
     | 
| 
       560 
601 
     | 
    
         
             
                  # responding to the +id+ and executes delete on them.
         
     | 
| 
       561 
602 
     | 
    
         
             
                  #
         
     | 
| 
       562 
603 
     | 
    
         
             
                  #   class Person < ActiveRecord::Base
         
     | 
| 
         @@ -618,9 +659,9 @@ module ActiveRecord 
     | 
|
| 
       618 
659 
     | 
    
         
             
                  #   person.pets.size  # => 0
         
     | 
| 
       619 
660 
     | 
    
         
             
                  #   person.pets       # => []
         
     | 
| 
       620 
661 
     | 
    
         
             
                  #
         
     | 
| 
       621 
     | 
    
         
            -
                  #   Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with  
     | 
| 
      
 662 
     | 
    
         
            +
                  #   Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
         
     | 
| 
       622 
663 
     | 
    
         
             
                  #
         
     | 
| 
       623 
     | 
    
         
            -
                  # You can pass + 
     | 
| 
      
 664 
     | 
    
         
            +
                  # You can pass +Integer+ or +String+ values, it finds the records
         
     | 
| 
       624 
665 
     | 
    
         
             
                  # responding to the +id+ and then deletes them from the database.
         
     | 
| 
       625 
666 
     | 
    
         
             
                  #
         
     | 
| 
       626 
667 
     | 
    
         
             
                  #   person.pets.size # => 3
         
     | 
| 
         @@ -650,7 +691,7 @@ module ActiveRecord 
     | 
|
| 
       650 
691 
     | 
    
         
             
                  #   person.pets.size  # => 0
         
     | 
| 
       651 
692 
     | 
    
         
             
                  #   person.pets       # => []
         
     | 
| 
       652 
693 
     | 
    
         
             
                  #
         
     | 
| 
       653 
     | 
    
         
            -
                  #   Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with  
     | 
| 
      
 694 
     | 
    
         
            +
                  #   Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)
         
     | 
| 
       654 
695 
     | 
    
         
             
                  def destroy(*records)
         
     | 
| 
       655 
696 
     | 
    
         
             
                    @association.destroy(*records)
         
     | 
| 
       656 
697 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -687,10 +728,8 @@ module ActiveRecord 
     | 
|
| 
       687 
728 
     | 
    
         
             
                  #   #       #<Pet id: 2, name: "Spook", person_id: 1>,
         
     | 
| 
       688 
729 
     | 
    
         
             
                  #   #       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
         
     | 
| 
       689 
730 
     | 
    
         
             
                  #   #    ]
         
     | 
| 
       690 
     | 
    
         
            -
                  def count(column_name = nil 
     | 
| 
       691 
     | 
    
         
            -
                     
     | 
| 
       692 
     | 
    
         
            -
                    # activerecord-deprecated_finders.
         
     | 
| 
       693 
     | 
    
         
            -
                    @association.count(column_name, options)
         
     | 
| 
      
 731 
     | 
    
         
            +
                  def count(column_name = nil)
         
     | 
| 
      
 732 
     | 
    
         
            +
                    @association.count(column_name)
         
     | 
| 
       694 
733 
     | 
    
         
             
                  end
         
     | 
| 
       695 
734 
     | 
    
         | 
| 
       696 
735 
     | 
    
         
             
                  # Returns the size of the collection. If the collection hasn't been loaded,
         
     | 
| 
         @@ -777,7 +816,7 @@ module ActiveRecord 
     | 
|
| 
       777 
816 
     | 
    
         
             
                  #   person.pets.any?  # => false
         
     | 
| 
       778 
817 
     | 
    
         
             
                  #
         
     | 
| 
       779 
818 
     | 
    
         
             
                  #   person.pets << Pet.new(name: 'Snoop')
         
     | 
| 
       780 
     | 
    
         
            -
                  #   person.pets.count # =>  
     | 
| 
      
 819 
     | 
    
         
            +
                  #   person.pets.count # => 1
         
     | 
| 
       781 
820 
     | 
    
         
             
                  #   person.pets.any?  # => true
         
     | 
| 
       782 
821 
     | 
    
         
             
                  #
         
     | 
| 
       783 
822 
     | 
    
         
             
                  # You can also pass a +block+ to define criteria. The behavior
         
     | 
| 
         @@ -852,7 +891,7 @@ module ActiveRecord 
     | 
|
| 
       852 
891 
     | 
    
         
             
                    !!@association.include?(record)
         
     | 
| 
       853 
892 
     | 
    
         
             
                  end
         
     | 
| 
       854 
893 
     | 
    
         | 
| 
       855 
     | 
    
         
            -
                  def arel
         
     | 
| 
      
 894 
     | 
    
         
            +
                  def arel #:nodoc:
         
     | 
| 
       856 
895 
     | 
    
         
             
                    scope.arel
         
     | 
| 
       857 
896 
     | 
    
         
             
                  end
         
     | 
| 
       858 
897 
     | 
    
         | 
| 
         @@ -940,6 +979,10 @@ module ActiveRecord 
     | 
|
| 
       940 
979 
     | 
    
         
             
                  end
         
     | 
| 
       941 
980 
     | 
    
         
             
                  alias_method :to_a, :to_ary
         
     | 
| 
       942 
981 
     | 
    
         | 
| 
      
 982 
     | 
    
         
            +
                  def records # :nodoc:
         
     | 
| 
      
 983 
     | 
    
         
            +
                    load_target
         
     | 
| 
      
 984 
     | 
    
         
            +
                  end
         
     | 
| 
      
 985 
     | 
    
         
            +
             
     | 
| 
       943 
986 
     | 
    
         
             
                  # Adds one or more +records+ to the collection by setting their foreign keys
         
     | 
| 
       944 
987 
     | 
    
         
             
                  # to the association's primary key. Returns +self+, so several appends may be
         
     | 
| 
       945 
988 
     | 
    
         
             
                  # chained together.
         
     | 
| 
         @@ -967,12 +1010,15 @@ module ActiveRecord 
     | 
|
| 
       967 
1010 
     | 
    
         
             
                  alias_method :append, :<<
         
     | 
| 
       968 
1011 
     | 
    
         | 
| 
       969 
1012 
     | 
    
         
             
                  def prepend(*args)
         
     | 
| 
       970 
     | 
    
         
            -
                    raise NoMethodError, "prepend on association is not defined. Please use  
     | 
| 
      
 1013 
     | 
    
         
            +
                    raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
         
     | 
| 
       971 
1014 
     | 
    
         
             
                  end
         
     | 
| 
       972 
1015 
     | 
    
         | 
| 
       973 
1016 
     | 
    
         
             
                  # Equivalent to +delete_all+. The difference is that returns +self+, instead
         
     | 
| 
       974 
1017 
     | 
    
         
             
                  # of an array with the deleted objects, so methods can be chained. See
         
     | 
| 
       975 
1018 
     | 
    
         
             
                  # +delete_all+ for more information.
         
     | 
| 
      
 1019 
     | 
    
         
            +
                  # Note that because +delete_all+ removes records by directly
         
     | 
| 
      
 1020 
     | 
    
         
            +
                  # running an SQL query into the database, the +updated_at+ column of
         
     | 
| 
      
 1021 
     | 
    
         
            +
                  # the object is not changed.
         
     | 
| 
       976 
1022 
     | 
    
         
             
                  def clear
         
     | 
| 
       977 
1023 
     | 
    
         
             
                    delete_all
         
     | 
| 
       978 
1024 
     | 
    
         
             
                    self
         
     | 
| 
         @@ -6,6 +6,7 @@ module ActiveRecord 
     | 
|
| 
       6 
6 
     | 
    
         
             
                # If the association has a <tt>:through</tt> option further specialization
         
     | 
| 
       7 
7 
     | 
    
         
             
                # is provided by its child HasManyThroughAssociation.
         
     | 
| 
       8 
8 
     | 
    
         
             
                class HasManyAssociation < CollectionAssociation #:nodoc:
         
     | 
| 
      
 9 
     | 
    
         
            +
                  include ForeignAssociation
         
     | 
| 
       9 
10 
     | 
    
         | 
| 
       10 
11 
     | 
    
         
             
                  def handle_dependency
         
     | 
| 
       11 
12 
     | 
    
         
             
                    case options[:dependent]
         
     | 
| 
         @@ -14,9 +15,16 @@ module ActiveRecord 
     | 
|
| 
       14 
15 
     | 
    
         | 
| 
       15 
16 
     | 
    
         
             
                    when :restrict_with_error
         
     | 
| 
       16 
17 
     | 
    
         
             
                      unless empty?
         
     | 
| 
       17 
     | 
    
         
            -
                        record =  
     | 
| 
       18 
     | 
    
         
            -
                        owner.errors. 
     | 
| 
       19 
     | 
    
         
            -
                         
     | 
| 
      
 18 
     | 
    
         
            +
                        record = owner.class.human_attribute_name(reflection.name).downcase
         
     | 
| 
      
 19 
     | 
    
         
            +
                        message = owner.errors.generate_message(:base, :'restrict_dependent_destroy.many', record: record, raise: true) rescue nil
         
     | 
| 
      
 20 
     | 
    
         
            +
                        if message
         
     | 
| 
      
 21 
     | 
    
         
            +
                          ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
         
     | 
| 
      
 22 
     | 
    
         
            +
                            The error key `:'restrict_dependent_destroy.many'` has been deprecated and will be removed in Rails 5.1.
         
     | 
| 
      
 23 
     | 
    
         
            +
                            Please use `:'restrict_dependent_destroy.has_many'` instead.
         
     | 
| 
      
 24 
     | 
    
         
            +
                          MESSAGE
         
     | 
| 
      
 25 
     | 
    
         
            +
                        end
         
     | 
| 
      
 26 
     | 
    
         
            +
                        owner.errors.add(:base, message || :'restrict_dependent_destroy.has_many', record: record)
         
     | 
| 
      
 27 
     | 
    
         
            +
                        throw(:abort)
         
     | 
| 
       20 
28 
     | 
    
         
             
                      end
         
     | 
| 
       21 
29 
     | 
    
         | 
| 
       22 
30 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -42,7 +50,7 @@ module ActiveRecord 
     | 
|
| 
       42 
50 
     | 
    
         
             
                  end
         
     | 
| 
       43 
51 
     | 
    
         | 
| 
       44 
52 
     | 
    
         
             
                  def empty?
         
     | 
| 
       45 
     | 
    
         
            -
                    if has_cached_counter?
         
     | 
| 
      
 53 
     | 
    
         
            +
                    if reflection.has_cached_counter?
         
     | 
| 
       46 
54 
     | 
    
         
             
                      size.zero?
         
     | 
| 
       47 
55 
     | 
    
         
             
                    else
         
     | 
| 
       48 
56 
     | 
    
         
             
                      super
         
     | 
| 
         @@ -65,8 +73,8 @@ module ActiveRecord 
     | 
|
| 
       65 
73 
     | 
    
         
             
                    # If the collection is empty the target is set to an empty array and
         
     | 
| 
       66 
74 
     | 
    
         
             
                    # the loaded flag is set to true as well.
         
     | 
| 
       67 
75 
     | 
    
         
             
                    def count_records
         
     | 
| 
       68 
     | 
    
         
            -
                      count = if has_cached_counter?
         
     | 
| 
       69 
     | 
    
         
            -
                        owner._read_attribute  
     | 
| 
      
 76 
     | 
    
         
            +
                      count = if reflection.has_cached_counter?
         
     | 
| 
      
 77 
     | 
    
         
            +
                        owner._read_attribute reflection.counter_cache_column
         
     | 
| 
       70 
78 
     | 
    
         
             
                      else
         
     | 
| 
       71 
79 
     | 
    
         
             
                        scope.count
         
     | 
| 
       72 
80 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -79,56 +87,20 @@ module ActiveRecord 
     | 
|
| 
       79 
87 
     | 
    
         
             
                      [association_scope.limit_value, count].compact.min
         
     | 
| 
       80 
88 
     | 
    
         
             
                    end
         
     | 
| 
       81 
89 
     | 
    
         | 
| 
       82 
     | 
    
         
            -
                    def has_cached_counter?(reflection = reflection())
         
     | 
| 
       83 
     | 
    
         
            -
                      owner.attribute_present?(cached_counter_attribute_name(reflection))
         
     | 
| 
       84 
     | 
    
         
            -
                    end
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                    def cached_counter_attribute_name(reflection = reflection())
         
     | 
| 
       87 
     | 
    
         
            -
                      options[:counter_cache] || "#{reflection.name}_count"
         
     | 
| 
       88 
     | 
    
         
            -
                    end
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
90 
     | 
    
         
             
                    def update_counter(difference, reflection = reflection())
         
     | 
| 
       91 
     | 
    
         
            -
                       
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                    end
         
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
                    def update_counter_in_database(difference, reflection = reflection())
         
     | 
| 
       96 
     | 
    
         
            -
                      if has_cached_counter?(reflection)
         
     | 
| 
       97 
     | 
    
         
            -
                        counter = cached_counter_attribute_name(reflection)
         
     | 
| 
       98 
     | 
    
         
            -
                        owner.class.update_counters(owner.id, counter => difference)
         
     | 
| 
      
 91 
     | 
    
         
            +
                      if reflection.has_cached_counter?
         
     | 
| 
      
 92 
     | 
    
         
            +
                        owner.increment!(reflection.counter_cache_column, difference)
         
     | 
| 
       99 
93 
     | 
    
         
             
                      end
         
     | 
| 
       100 
94 
     | 
    
         
             
                    end
         
     | 
| 
       101 
95 
     | 
    
         | 
| 
       102 
96 
     | 
    
         
             
                    def update_counter_in_memory(difference, reflection = reflection())
         
     | 
| 
       103 
     | 
    
         
            -
                      if  
     | 
| 
       104 
     | 
    
         
            -
                        counter =  
     | 
| 
       105 
     | 
    
         
            -
                        owner 
     | 
| 
       106 
     | 
    
         
            -
                        owner.send(: 
     | 
| 
      
 97 
     | 
    
         
            +
                      if reflection.counter_must_be_updated_by_has_many?
         
     | 
| 
      
 98 
     | 
    
         
            +
                        counter = reflection.counter_cache_column
         
     | 
| 
      
 99 
     | 
    
         
            +
                        owner.increment(counter, difference)
         
     | 
| 
      
 100 
     | 
    
         
            +
                        owner.send(:clear_attribute_change, counter) # eww
         
     | 
| 
       107 
101 
     | 
    
         
             
                      end
         
     | 
| 
       108 
102 
     | 
    
         
             
                    end
         
     | 
| 
       109 
103 
     | 
    
         | 
| 
       110 
     | 
    
         
            -
                    # This shit is nasty. We need to avoid the following situation:
         
     | 
| 
       111 
     | 
    
         
            -
                    #
         
     | 
| 
       112 
     | 
    
         
            -
                    #   * An associated record is deleted via record.destroy
         
     | 
| 
       113 
     | 
    
         
            -
                    #   * Hence the callbacks run, and they find a belongs_to on the record with a
         
     | 
| 
       114 
     | 
    
         
            -
                    #     :counter_cache options which points back at our owner. So they update the
         
     | 
| 
       115 
     | 
    
         
            -
                    #     counter cache.
         
     | 
| 
       116 
     | 
    
         
            -
                    #   * In which case, we must make sure to *not* update the counter cache, or else
         
     | 
| 
       117 
     | 
    
         
            -
                    #     it will be decremented twice.
         
     | 
| 
       118 
     | 
    
         
            -
                    #
         
     | 
| 
       119 
     | 
    
         
            -
                    # Hence this method.
         
     | 
| 
       120 
     | 
    
         
            -
                    def inverse_updates_counter_cache?(reflection = reflection())
         
     | 
| 
       121 
     | 
    
         
            -
                      counter_name = cached_counter_attribute_name(reflection)
         
     | 
| 
       122 
     | 
    
         
            -
                      inverse_updates_counter_named?(counter_name, reflection)
         
     | 
| 
       123 
     | 
    
         
            -
                    end
         
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
       125 
     | 
    
         
            -
                    def inverse_updates_counter_named?(counter_name, reflection = reflection())
         
     | 
| 
       126 
     | 
    
         
            -
                      reflection.klass._reflections.values.any? { |inverse_reflection|
         
     | 
| 
       127 
     | 
    
         
            -
                        inverse_reflection.belongs_to? &&
         
     | 
| 
       128 
     | 
    
         
            -
                        inverse_reflection.counter_cache_column == counter_name
         
     | 
| 
       129 
     | 
    
         
            -
                      }
         
     | 
| 
       130 
     | 
    
         
            -
                    end
         
     | 
| 
       131 
     | 
    
         
            -
             
     | 
| 
       132 
104 
     | 
    
         
             
                    def delete_count(method, scope)
         
     | 
| 
       133 
105 
     | 
    
         
             
                      if method == :delete_all
         
     | 
| 
       134 
106 
     | 
    
         
             
                        scope.delete_all
         
     | 
| 
         @@ -146,21 +118,13 @@ module ActiveRecord 
     | 
|
| 
       146 
118 
     | 
    
         
             
                    def delete_records(records, method)
         
     | 
| 
       147 
119 
     | 
    
         
             
                      if method == :destroy
         
     | 
| 
       148 
120 
     | 
    
         
             
                        records.each(&:destroy!)
         
     | 
| 
       149 
     | 
    
         
            -
                        update_counter(-records.length) unless inverse_updates_counter_cache?
         
     | 
| 
      
 121 
     | 
    
         
            +
                        update_counter(-records.length) unless reflection.inverse_updates_counter_cache?
         
     | 
| 
       150 
122 
     | 
    
         
             
                      else
         
     | 
| 
       151 
123 
     | 
    
         
             
                        scope = self.scope.where(reflection.klass.primary_key => records)
         
     | 
| 
       152 
124 
     | 
    
         
             
                        update_counter(-delete_count(method, scope))
         
     | 
| 
       153 
125 
     | 
    
         
             
                      end
         
     | 
| 
       154 
126 
     | 
    
         
             
                    end
         
     | 
| 
       155 
127 
     | 
    
         | 
| 
       156 
     | 
    
         
            -
                    def foreign_key_present?
         
     | 
| 
       157 
     | 
    
         
            -
                      if reflection.klass.primary_key
         
     | 
| 
       158 
     | 
    
         
            -
                        owner.attribute_present?(reflection.association_primary_key)
         
     | 
| 
       159 
     | 
    
         
            -
                      else
         
     | 
| 
       160 
     | 
    
         
            -
                        false
         
     | 
| 
       161 
     | 
    
         
            -
                      end
         
     | 
| 
       162 
     | 
    
         
            -
                    end
         
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
128 
     | 
    
         
             
                    def concat_records(records, *)
         
     | 
| 
       165 
129 
     | 
    
         
             
                      update_counter_if_success(super, records.length)
         
     | 
| 
       166 
130 
     | 
    
         
             
                    end
         
     |