activerecord 3.2.22.4 → 4.0.13
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 +2799 -617
 - data/MIT-LICENSE +1 -1
 - data/README.rdoc +23 -32
 - data/examples/performance.rb +1 -1
 - data/lib/active_record/aggregations.rb +40 -34
 - data/lib/active_record/association_relation.rb +22 -0
 - data/lib/active_record/associations/alias_tracker.rb +4 -2
 - data/lib/active_record/associations/association.rb +60 -46
 - data/lib/active_record/associations/association_scope.rb +46 -40
 - data/lib/active_record/associations/belongs_to_association.rb +17 -4
 - data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
 - data/lib/active_record/associations/builder/association.rb +81 -28
 - data/lib/active_record/associations/builder/belongs_to.rb +73 -56
 - data/lib/active_record/associations/builder/collection_association.rb +54 -40
 - data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
 - data/lib/active_record/associations/builder/has_many.rb +8 -64
 - data/lib/active_record/associations/builder/has_one.rb +13 -50
 - data/lib/active_record/associations/builder/singular_association.rb +13 -13
 - data/lib/active_record/associations/collection_association.rb +130 -96
 - data/lib/active_record/associations/collection_proxy.rb +916 -63
 - data/lib/active_record/associations/has_and_belongs_to_many_association.rb +15 -13
 - data/lib/active_record/associations/has_many_association.rb +35 -8
 - data/lib/active_record/associations/has_many_through_association.rb +37 -17
 - data/lib/active_record/associations/has_one_association.rb +42 -19
 - data/lib/active_record/associations/has_one_through_association.rb +1 -1
 - data/lib/active_record/associations/join_dependency/join_association.rb +39 -22
 - data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
 - data/lib/active_record/associations/join_dependency/join_part.rb +21 -8
 - data/lib/active_record/associations/join_dependency.rb +30 -9
 - data/lib/active_record/associations/join_helper.rb +1 -11
 - data/lib/active_record/associations/preloader/association.rb +29 -33
 - data/lib/active_record/associations/preloader/collection_association.rb +1 -1
 - data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +2 -2
 - data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
 - data/lib/active_record/associations/preloader/has_one.rb +1 -1
 - data/lib/active_record/associations/preloader/through_association.rb +13 -17
 - data/lib/active_record/associations/preloader.rb +20 -43
 - data/lib/active_record/associations/singular_association.rb +11 -11
 - data/lib/active_record/associations/through_association.rb +3 -3
 - data/lib/active_record/associations.rb +223 -282
 - data/lib/active_record/attribute_assignment.rb +134 -154
 - data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
 - data/lib/active_record/attribute_methods/dirty.rb +36 -29
 - data/lib/active_record/attribute_methods/primary_key.rb +45 -31
 - data/lib/active_record/attribute_methods/query.rb +5 -4
 - data/lib/active_record/attribute_methods/read.rb +67 -90
 - data/lib/active_record/attribute_methods/serialization.rb +133 -70
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +51 -45
 - data/lib/active_record/attribute_methods/write.rb +34 -39
 - data/lib/active_record/attribute_methods.rb +268 -108
 - data/lib/active_record/autosave_association.rb +80 -73
 - data/lib/active_record/base.rb +54 -451
 - data/lib/active_record/callbacks.rb +60 -22
 - data/lib/active_record/coders/yaml_column.rb +18 -21
 - data/lib/active_record/connection_adapters/abstract/connection_pool.rb +347 -197
 - data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
 - data/lib/active_record/connection_adapters/abstract/database_statements.rb +146 -138
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +25 -19
 - data/lib/active_record/connection_adapters/abstract/quoting.rb +19 -3
 - data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +151 -142
 - data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +499 -217
 - data/lib/active_record/connection_adapters/abstract/transaction.rb +208 -0
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +209 -44
 - data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +169 -61
 - data/lib/active_record/connection_adapters/column.rb +67 -36
 - data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +28 -29
 - data/lib/active_record/connection_adapters/mysql_adapter.rb +200 -73
 - data/lib/active_record/connection_adapters/postgresql/array_parser.rb +98 -0
 - data/lib/active_record/connection_adapters/postgresql/cast.rb +160 -0
 - data/lib/active_record/connection_adapters/postgresql/database_statements.rb +240 -0
 - data/lib/active_record/connection_adapters/postgresql/oid.rb +374 -0
 - data/lib/active_record/connection_adapters/postgresql/quoting.rb +183 -0
 - data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
 - data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +508 -0
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +544 -899
 - data/lib/active_record/connection_adapters/schema_cache.rb +76 -16
 - data/lib/active_record/connection_adapters/sqlite3_adapter.rb +595 -16
 - data/lib/active_record/connection_handling.rb +98 -0
 - data/lib/active_record/core.rb +472 -0
 - data/lib/active_record/counter_cache.rb +107 -108
 - data/lib/active_record/dynamic_matchers.rb +115 -63
 - data/lib/active_record/errors.rb +36 -18
 - data/lib/active_record/explain.rb +15 -63
 - data/lib/active_record/explain_registry.rb +30 -0
 - data/lib/active_record/explain_subscriber.rb +8 -4
 - data/lib/active_record/fixture_set/file.rb +55 -0
 - data/lib/active_record/fixtures.rb +159 -155
 - data/lib/active_record/inheritance.rb +93 -59
 - data/lib/active_record/integration.rb +8 -8
 - data/lib/active_record/locale/en.yml +8 -1
 - data/lib/active_record/locking/optimistic.rb +39 -43
 - data/lib/active_record/locking/pessimistic.rb +4 -4
 - data/lib/active_record/log_subscriber.rb +19 -9
 - data/lib/active_record/migration/command_recorder.rb +102 -33
 - data/lib/active_record/migration/join_table.rb +15 -0
 - data/lib/active_record/migration.rb +411 -173
 - data/lib/active_record/model_schema.rb +81 -94
 - data/lib/active_record/nested_attributes.rb +173 -131
 - data/lib/active_record/null_relation.rb +67 -0
 - data/lib/active_record/persistence.rb +254 -106
 - data/lib/active_record/query_cache.rb +18 -36
 - data/lib/active_record/querying.rb +19 -15
 - data/lib/active_record/railtie.rb +113 -38
 - data/lib/active_record/railties/console_sandbox.rb +3 -4
 - data/lib/active_record/railties/controller_runtime.rb +4 -3
 - data/lib/active_record/railties/databases.rake +115 -368
 - data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
 - data/lib/active_record/readonly_attributes.rb +7 -3
 - data/lib/active_record/reflection.rb +110 -61
 - data/lib/active_record/relation/batches.rb +29 -29
 - data/lib/active_record/relation/calculations.rb +155 -125
 - data/lib/active_record/relation/delegation.rb +94 -18
 - data/lib/active_record/relation/finder_methods.rb +151 -203
 - data/lib/active_record/relation/merger.rb +188 -0
 - data/lib/active_record/relation/predicate_builder.rb +85 -42
 - data/lib/active_record/relation/query_methods.rb +793 -146
 - data/lib/active_record/relation/spawn_methods.rb +43 -150
 - data/lib/active_record/relation.rb +293 -173
 - data/lib/active_record/result.rb +48 -7
 - data/lib/active_record/runtime_registry.rb +17 -0
 - data/lib/active_record/sanitization.rb +41 -54
 - data/lib/active_record/schema.rb +19 -12
 - data/lib/active_record/schema_dumper.rb +41 -41
 - data/lib/active_record/schema_migration.rb +46 -0
 - data/lib/active_record/scoping/default.rb +56 -52
 - data/lib/active_record/scoping/named.rb +78 -103
 - data/lib/active_record/scoping.rb +54 -124
 - data/lib/active_record/serialization.rb +6 -2
 - data/lib/active_record/serializers/xml_serializer.rb +9 -15
 - data/lib/active_record/statement_cache.rb +26 -0
 - data/lib/active_record/store.rb +131 -15
 - data/lib/active_record/tasks/database_tasks.rb +204 -0
 - data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
 - data/lib/active_record/tasks/mysql_database_tasks.rb +144 -0
 - data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
 - data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
 - data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
 - data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
 - data/lib/active_record/test_case.rb +67 -38
 - data/lib/active_record/timestamp.rb +16 -11
 - data/lib/active_record/transactions.rb +73 -51
 - data/lib/active_record/validations/associated.rb +19 -13
 - data/lib/active_record/validations/presence.rb +65 -0
 - data/lib/active_record/validations/uniqueness.rb +110 -57
 - data/lib/active_record/validations.rb +18 -17
 - data/lib/active_record/version.rb +7 -6
 - data/lib/active_record.rb +63 -45
 - data/lib/rails/generators/active_record/migration/migration_generator.rb +45 -8
 - data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
 - data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
 - data/lib/rails/generators/active_record/model/model_generator.rb +5 -4
 - data/lib/rails/generators/active_record/model/templates/model.rb +4 -6
 - data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
 - data/lib/rails/generators/active_record.rb +3 -5
 - metadata +43 -29
 - data/examples/associations.png +0 -0
 - data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
 - data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
 - data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
 - data/lib/active_record/dynamic_finder_match.rb +0 -68
 - data/lib/active_record/dynamic_scope_match.rb +0 -23
 - data/lib/active_record/fixtures/file.rb +0 -65
 - data/lib/active_record/identity_map.rb +0 -162
 - data/lib/active_record/observer.rb +0 -121
 - data/lib/active_record/session_store.rb +0 -360
 - data/lib/rails/generators/active_record/migration.rb +0 -15
 - data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
 - data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
 - data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
 - data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
 
    
        data/MIT-LICENSE
    CHANGED
    
    
    
        data/README.rdoc
    CHANGED
    
    | 
         @@ -49,10 +49,10 @@ A short rundown of some of the major features: 
     | 
|
| 
       49 
49 
     | 
    
         
             
            * Aggregations of value objects.
         
     | 
| 
       50 
50 
     | 
    
         | 
| 
       51 
51 
     | 
    
         
             
               class Account < ActiveRecord::Base
         
     | 
| 
       52 
     | 
    
         
            -
                 composed_of :balance, : 
     | 
| 
       53 
     | 
    
         
            -
                             : 
     | 
| 
      
 52 
     | 
    
         
            +
                 composed_of :balance, class_name: 'Money',
         
     | 
| 
      
 53 
     | 
    
         
            +
                             mapping: %w(balance amount)
         
     | 
| 
       54 
54 
     | 
    
         
             
                 composed_of :address,
         
     | 
| 
       55 
     | 
    
         
            -
                             : 
     | 
| 
      
 55 
     | 
    
         
            +
                             mapping: [%w(address_street street), %w(address_city city)]
         
     | 
| 
       56 
56 
     | 
    
         
             
               end
         
     | 
| 
       57 
57 
     | 
    
         | 
| 
       58 
58 
     | 
    
         
             
              {Learn more}[link:classes/ActiveRecord/Aggregations/ClassMethods.html]
         
     | 
| 
         @@ -61,10 +61,10 @@ A short rundown of some of the major features: 
     | 
|
| 
       61 
61 
     | 
    
         
             
            * Validation rules that can differ for new or existing objects.
         
     | 
| 
       62 
62 
     | 
    
         | 
| 
       63 
63 
     | 
    
         
             
                class Account < ActiveRecord::Base
         
     | 
| 
       64 
     | 
    
         
            -
                   
     | 
| 
       65 
     | 
    
         
            -
                   
     | 
| 
       66 
     | 
    
         
            -
                   
     | 
| 
       67 
     | 
    
         
            -
                   
     | 
| 
      
 64 
     | 
    
         
            +
                  validates :subdomain, :name, :email_address, :password, presence: true
         
     | 
| 
      
 65 
     | 
    
         
            +
                  validates :subdomain, uniqueness: true
         
     | 
| 
      
 66 
     | 
    
         
            +
                  validates :terms_of_service, acceptance: true, on: :create
         
     | 
| 
      
 67 
     | 
    
         
            +
                  validates :password, :email_address, confirmation: true, on: :create
         
     | 
| 
       68 
68 
     | 
    
         
             
                end
         
     | 
| 
       69 
69 
     | 
    
         | 
| 
       70 
70 
     | 
    
         
             
              {Learn more}[link:classes/ActiveRecord/Validations.html]
         
     | 
| 
         @@ -80,17 +80,6 @@ A short rundown of some of the major features: 
     | 
|
| 
       80 
80 
     | 
    
         
             
              {Learn more}[link:classes/ActiveRecord/Callbacks.html]
         
     | 
| 
       81 
81 
     | 
    
         | 
| 
       82 
82 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
            * Observers that react to changes in a model.
         
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
               class CommentObserver < ActiveRecord::Observer
         
     | 
| 
       86 
     | 
    
         
            -
                 def after_create(comment) # is called just after Comment#save
         
     | 
| 
       87 
     | 
    
         
            -
                   CommentMailer.new_comment_email("david@loudthinking.com", comment).deliver
         
     | 
| 
       88 
     | 
    
         
            -
                 end
         
     | 
| 
       89 
     | 
    
         
            -
               end
         
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
              {Learn more}[link:classes/ActiveRecord/Observer.html]
         
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
83 
     | 
    
         
             
            * Inheritance hierarchies.
         
     | 
| 
       95 
84 
     | 
    
         | 
| 
       96 
85 
     | 
    
         
             
               class Company < ActiveRecord::Base; end
         
     | 
| 
         @@ -124,15 +113,15 @@ A short rundown of some of the major features: 
     | 
|
| 
       124 
113 
     | 
    
         
             
            * Database abstraction through simple adapters.
         
     | 
| 
       125 
114 
     | 
    
         | 
| 
       126 
115 
     | 
    
         
             
                # connect to SQLite3
         
     | 
| 
       127 
     | 
    
         
            -
                ActiveRecord::Base.establish_connection(: 
     | 
| 
      
 116 
     | 
    
         
            +
                ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'dbfile.sqlite3')
         
     | 
| 
       128 
117 
     | 
    
         | 
| 
       129 
118 
     | 
    
         
             
                # connect to MySQL with authentication
         
     | 
| 
       130 
119 
     | 
    
         
             
                ActiveRecord::Base.establish_connection(
         
     | 
| 
       131 
     | 
    
         
            -
                  : 
     | 
| 
       132 
     | 
    
         
            -
                  : 
     | 
| 
       133 
     | 
    
         
            -
                  : 
     | 
| 
       134 
     | 
    
         
            -
                  : 
     | 
| 
       135 
     | 
    
         
            -
                  : 
     | 
| 
      
 120 
     | 
    
         
            +
                  adapter:  'mysql2',
         
     | 
| 
      
 121 
     | 
    
         
            +
                  host:     'localhost',
         
     | 
| 
      
 122 
     | 
    
         
            +
                  username: 'me',
         
     | 
| 
      
 123 
     | 
    
         
            +
                  password: 'secret',
         
     | 
| 
      
 124 
     | 
    
         
            +
                  database: 'activerecord'
         
     | 
| 
       136 
125 
     | 
    
         
             
                )
         
     | 
| 
       137 
126 
     | 
    
         | 
| 
       138 
127 
     | 
    
         
             
              {Learn more}[link:classes/ActiveRecord/Base.html] and read about the built-in support for
         
     | 
| 
         @@ -141,10 +130,10 @@ A short rundown of some of the major features: 
     | 
|
| 
       141 
130 
     | 
    
         
             
              SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
         
     | 
| 
       142 
131 
     | 
    
         | 
| 
       143 
132 
     | 
    
         | 
| 
       144 
     | 
    
         
            -
            * Logging support for Log4r[http://log4r. 
     | 
| 
      
 133 
     | 
    
         
            +
            * Logging support for Log4r[http://log4r.rubyforge.org] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc].
         
     | 
| 
       145 
134 
     | 
    
         | 
| 
       146 
     | 
    
         
            -
                ActiveRecord::Base.logger = Logger.new(STDOUT)
         
     | 
| 
       147 
     | 
    
         
            -
                ActiveRecord::Base.logger = Log4r::Logger.new( 
     | 
| 
      
 135 
     | 
    
         
            +
                ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT)
         
     | 
| 
      
 136 
     | 
    
         
            +
                ActiveRecord::Base.logger = Log4r::Logger.new('Application Log')
         
     | 
| 
       148 
137 
     | 
    
         | 
| 
       149 
138 
     | 
    
         | 
| 
       150 
139 
     | 
    
         
             
            * Database agnostic schema management with Migrations.
         
     | 
| 
         @@ -159,7 +148,7 @@ A short rundown of some of the major features: 
     | 
|
| 
       159 
148 
     | 
    
         
             
                      t.integer :position
         
     | 
| 
       160 
149 
     | 
    
         
             
                    end
         
     | 
| 
       161 
150 
     | 
    
         | 
| 
       162 
     | 
    
         
            -
                    SystemSetting.create : 
     | 
| 
      
 151 
     | 
    
         
            +
                    SystemSetting.create name: 'notice', label: 'Use notice?', value: 1
         
     | 
| 
       163 
152 
     | 
    
         
             
                  end
         
     | 
| 
       164 
153 
     | 
    
         | 
| 
       165 
154 
     | 
    
         
             
                  def down
         
     | 
| 
         @@ -201,19 +190,21 @@ The latest version of Active Record can be installed with RubyGems: 
     | 
|
| 
       201 
190 
     | 
    
         | 
| 
       202 
191 
     | 
    
         
             
              % [sudo] gem install activerecord
         
     | 
| 
       203 
192 
     | 
    
         | 
| 
       204 
     | 
    
         
            -
            Source code can be downloaded as part of the Rails project on GitHub
         
     | 
| 
      
 193 
     | 
    
         
            +
            Source code can be downloaded as part of the Rails project on GitHub:
         
     | 
| 
       205 
194 
     | 
    
         | 
| 
       206 
     | 
    
         
            -
            * https://github.com/rails/rails/tree/ 
     | 
| 
      
 195 
     | 
    
         
            +
            * https://github.com/rails/rails/tree/4-0-stable/activerecord
         
     | 
| 
       207 
196 
     | 
    
         | 
| 
       208 
197 
     | 
    
         | 
| 
       209 
198 
     | 
    
         
             
            == License
         
     | 
| 
       210 
199 
     | 
    
         | 
| 
       211 
     | 
    
         
            -
            Active Record is released under the MIT license 
     | 
| 
      
 200 
     | 
    
         
            +
            Active Record is released under the MIT license:
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
            * http://www.opensource.org/licenses/MIT
         
     | 
| 
       212 
203 
     | 
    
         | 
| 
       213 
204 
     | 
    
         | 
| 
       214 
205 
     | 
    
         
             
            == Support
         
     | 
| 
       215 
206 
     | 
    
         | 
| 
       216 
     | 
    
         
            -
            API documentation is at
         
     | 
| 
      
 207 
     | 
    
         
            +
            API documentation is at:
         
     | 
| 
       217 
208 
     | 
    
         | 
| 
       218 
209 
     | 
    
         
             
            * http://api.rubyonrails.org
         
     | 
| 
       219 
210 
     | 
    
         | 
    
        data/examples/performance.rb
    CHANGED
    
    
| 
         @@ -10,14 +10,14 @@ module ActiveRecord 
     | 
|
| 
       10 
10 
     | 
    
         
             
                # Active Record implements aggregation through a macro-like class method called +composed_of+
         
     | 
| 
       11 
11 
     | 
    
         
             
                # for representing attributes  as value objects. It expresses relationships like "Account [is]
         
     | 
| 
       12 
12 
     | 
    
         
             
                # composed of Money [among other things]" or "Person [is] composed of [an] address". Each call
         
     | 
| 
       13 
     | 
    
         
            -
                # to the macro adds a description of how the value objects 
     | 
| 
       14 
     | 
    
         
            -
                # the entity object (when the entity is initialized either 
     | 
| 
       15 
     | 
    
         
            -
                # existing object) and how it can be turned back into attributes 
     | 
| 
      
 13 
     | 
    
         
            +
                # to the macro adds a description of how the value objects are created from the attributes of
         
     | 
| 
      
 14 
     | 
    
         
            +
                # the entity object (when the entity is initialized either as a new object or from finding an
         
     | 
| 
      
 15 
     | 
    
         
            +
                # existing object) and how it can be turned back into attributes (when the entity is saved to
         
     | 
| 
       16 
16 
     | 
    
         
             
                # the database).
         
     | 
| 
       17 
17 
     | 
    
         
             
                #
         
     | 
| 
       18 
18 
     | 
    
         
             
                #   class Customer < ActiveRecord::Base
         
     | 
| 
       19 
     | 
    
         
            -
                #     composed_of :balance, : 
     | 
| 
       20 
     | 
    
         
            -
                #     composed_of :address, : 
     | 
| 
      
 19 
     | 
    
         
            +
                #     composed_of :balance, class_name: "Money", mapping: %w(balance amount)
         
     | 
| 
      
 20 
     | 
    
         
            +
                #     composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
         
     | 
| 
       21 
21 
     | 
    
         
             
                #   end
         
     | 
| 
       22 
22 
     | 
    
         
             
                #
         
     | 
| 
       23 
23 
     | 
    
         
             
                # The customer class now has the following methods to manipulate the value objects:
         
     | 
| 
         @@ -71,7 +71,7 @@ module ActiveRecord 
     | 
|
| 
       71 
71 
     | 
    
         
             
                # Now it's possible to access attributes from the database through the value objects instead. If
         
     | 
| 
       72 
72 
     | 
    
         
             
                # you choose to name the composition the same as the attribute's name, it will be the only way to
         
     | 
| 
       73 
73 
     | 
    
         
             
                # access that attribute. That's the case with our +balance+ attribute. You interact with the value
         
     | 
| 
       74 
     | 
    
         
            -
                # objects just like you would any other attribute 
     | 
| 
      
 74 
     | 
    
         
            +
                # objects just like you would with any other attribute:
         
     | 
| 
       75 
75 
     | 
    
         
             
                #
         
     | 
| 
       76 
76 
     | 
    
         
             
                #   customer.balance = Money.new(20)     # sets the Money value object and the attribute
         
     | 
| 
       77 
77 
     | 
    
         
             
                #   customer.balance                     # => Money value object
         
     | 
| 
         @@ -86,6 +86,12 @@ module ActiveRecord 
     | 
|
| 
       86 
86 
     | 
    
         
             
                #   customer.address_street = "Hyancintvej"
         
     | 
| 
       87 
87 
     | 
    
         
             
                #   customer.address_city   = "Copenhagen"
         
     | 
| 
       88 
88 
     | 
    
         
             
                #   customer.address        # => Address.new("Hyancintvej", "Copenhagen")
         
     | 
| 
      
 89 
     | 
    
         
            +
                #
         
     | 
| 
      
 90 
     | 
    
         
            +
                #   customer.address_street = "Vesterbrogade"
         
     | 
| 
      
 91 
     | 
    
         
            +
                #   customer.address        # => Address.new("Hyancintvej", "Copenhagen")
         
     | 
| 
      
 92 
     | 
    
         
            +
                #   customer.clear_aggregation_cache
         
     | 
| 
      
 93 
     | 
    
         
            +
                #   customer.address        # => Address.new("Vesterbrogade", "Copenhagen")
         
     | 
| 
      
 94 
     | 
    
         
            +
                #
         
     | 
| 
       89 
95 
     | 
    
         
             
                #   customer.address = Address.new("May Street", "Chicago")
         
     | 
| 
       90 
96 
     | 
    
         
             
                #   customer.address_street # => "May Street"
         
     | 
| 
       91 
97 
     | 
    
         
             
                #   customer.address_city   # => "Chicago"
         
     | 
| 
         @@ -101,13 +107,13 @@ module ActiveRecord 
     | 
|
| 
       101 
107 
     | 
    
         
             
                # ActiveRecord::Base classes are entity objects.
         
     | 
| 
       102 
108 
     | 
    
         
             
                #
         
     | 
| 
       103 
109 
     | 
    
         
             
                # It's also important to treat the value objects as immutable. Don't allow the Money object to have
         
     | 
| 
       104 
     | 
    
         
            -
                # its amount changed after creation. Create a new Money object with the new value instead.  
     | 
| 
       105 
     | 
    
         
            -
                # is  
     | 
| 
      
 110 
     | 
    
         
            +
                # its amount changed after creation. Create a new Money object with the new value instead. The
         
     | 
| 
      
 111 
     | 
    
         
            +
                # Money#exchange_to method is an example of this. It returns a new value object instead of changing
         
     | 
| 
       106 
112 
     | 
    
         
             
                # its own values. Active Record won't persist value objects that have been changed through means
         
     | 
| 
       107 
113 
     | 
    
         
             
                # other than the writer method.
         
     | 
| 
       108 
114 
     | 
    
         
             
                #
         
     | 
| 
       109 
115 
     | 
    
         
             
                # The immutable requirement is enforced by Active Record by freezing any object assigned as a value
         
     | 
| 
       110 
     | 
    
         
            -
                # object. Attempting to change it afterwards will result in a  
     | 
| 
      
 116 
     | 
    
         
            +
                # object. Attempting to change it afterwards will result in a RuntimeError.
         
     | 
| 
       111 
117 
     | 
    
         
             
                #
         
     | 
| 
       112 
118 
     | 
    
         
             
                # Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not
         
     | 
| 
       113 
119 
     | 
    
         
             
                # keeping value objects immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable
         
     | 
| 
         @@ -119,7 +125,7 @@ module ActiveRecord 
     | 
|
| 
       119 
125 
     | 
    
         
             
                # option, as arguments. If the value class doesn't support this convention then +composed_of+ allows
         
     | 
| 
       120 
126 
     | 
    
         
             
                # a custom constructor to be specified.
         
     | 
| 
       121 
127 
     | 
    
         
             
                #
         
     | 
| 
       122 
     | 
    
         
            -
                # When a new value is assigned to the value object the default assumption is that the new value
         
     | 
| 
      
 128 
     | 
    
         
            +
                # When a new value is assigned to the value object, the default assumption is that the new value
         
     | 
| 
       123 
129 
     | 
    
         
             
                # is an instance of the value class. Specifying a custom converter allows the new value to be automatically
         
     | 
| 
       124 
130 
     | 
    
         
             
                # converted to an instance of value class if necessary.
         
     | 
| 
       125 
131 
     | 
    
         
             
                #
         
     | 
| 
         @@ -132,15 +138,15 @@ module ActiveRecord 
     | 
|
| 
       132 
138 
     | 
    
         
             
                #
         
     | 
| 
       133 
139 
     | 
    
         
             
                #   class NetworkResource < ActiveRecord::Base
         
     | 
| 
       134 
140 
     | 
    
         
             
                #     composed_of :cidr,
         
     | 
| 
       135 
     | 
    
         
            -
                #                 : 
     | 
| 
       136 
     | 
    
         
            -
                #                 : 
     | 
| 
       137 
     | 
    
         
            -
                #                 : 
     | 
| 
       138 
     | 
    
         
            -
                #                 : 
     | 
| 
       139 
     | 
    
         
            -
                #                 : 
     | 
| 
      
 141 
     | 
    
         
            +
                #                 class_name: 'NetAddr::CIDR',
         
     | 
| 
      
 142 
     | 
    
         
            +
                #                 mapping: [ %w(network_address network), %w(cidr_range bits) ],
         
     | 
| 
      
 143 
     | 
    
         
            +
                #                 allow_nil: true,
         
     | 
| 
      
 144 
     | 
    
         
            +
                #                 constructor: Proc.new { |network_address, cidr_range| NetAddr::CIDR.create("#{network_address}/#{cidr_range}") },
         
     | 
| 
      
 145 
     | 
    
         
            +
                #                 converter: Proc.new { |value| NetAddr::CIDR.create(value.is_a?(Array) ? value.join('/') : value) }
         
     | 
| 
       140 
146 
     | 
    
         
             
                #   end
         
     | 
| 
       141 
147 
     | 
    
         
             
                #
         
     | 
| 
       142 
148 
     | 
    
         
             
                #   # This calls the :constructor
         
     | 
| 
       143 
     | 
    
         
            -
                #   network_resource = NetworkResource.new(: 
     | 
| 
      
 149 
     | 
    
         
            +
                #   network_resource = NetworkResource.new(network_address: '192.168.0.1', cidr_range: 24)
         
     | 
| 
       144 
150 
     | 
    
         
             
                #
         
     | 
| 
       145 
151 
     | 
    
         
             
                #   # These assignments will both use the :converter
         
     | 
| 
       146 
152 
     | 
    
         
             
                #   network_resource.cidr = [ '192.168.2.1', 8 ]
         
     | 
| 
         @@ -159,7 +165,7 @@ module ActiveRecord 
     | 
|
| 
       159 
165 
     | 
    
         
             
                # by specifying an instance of the value object in the conditions hash. The following example
         
     | 
| 
       160 
166 
     | 
    
         
             
                # finds all customers with +balance_amount+ equal to 20 and +balance_currency+ equal to "USD":
         
     | 
| 
       161 
167 
     | 
    
         
             
                #
         
     | 
| 
       162 
     | 
    
         
            -
                #   Customer.where(: 
     | 
| 
      
 168 
     | 
    
         
            +
                #   Customer.where(balance: Money.new(20, "USD"))
         
     | 
| 
       163 
169 
     | 
    
         
             
                #
         
     | 
| 
       164 
170 
     | 
    
         
             
                module ClassMethods
         
     | 
| 
       165 
171 
     | 
    
         
             
                  # Adds reader and writer methods for manipulating a value object:
         
     | 
| 
         @@ -187,20 +193,21 @@ module ActiveRecord 
     | 
|
| 
       187 
193 
     | 
    
         
             
                  # * <tt>:converter</tt> - A symbol specifying the name of a class method of <tt>:class_name</tt>
         
     | 
| 
       188 
194 
     | 
    
         
             
                  #   or a Proc that is called when a new value is assigned to the value object. The converter is
         
     | 
| 
       189 
195 
     | 
    
         
             
                  #   passed the single value that is used in the assignment and is only called if the new value is
         
     | 
| 
       190 
     | 
    
         
            -
                  #   not an instance of <tt>:class_name</tt>.
         
     | 
| 
      
 196 
     | 
    
         
            +
                  #   not an instance of <tt>:class_name</tt>. If <tt>:allow_nil</tt> is set to true, the converter
         
     | 
| 
      
 197 
     | 
    
         
            +
                  #   can return nil to skip the assignment.
         
     | 
| 
       191 
198 
     | 
    
         
             
                  #
         
     | 
| 
       192 
199 
     | 
    
         
             
                  # Option examples:
         
     | 
| 
       193 
     | 
    
         
            -
                  #   composed_of :temperature, : 
     | 
| 
       194 
     | 
    
         
            -
                  #   composed_of :balance, : 
     | 
| 
       195 
     | 
    
         
            -
                  #                         : 
     | 
| 
       196 
     | 
    
         
            -
                  #   composed_of :address, : 
     | 
| 
      
 200 
     | 
    
         
            +
                  #   composed_of :temperature, mapping: %w(reading celsius)
         
     | 
| 
      
 201 
     | 
    
         
            +
                  #   composed_of :balance, class_name: "Money", mapping: %w(balance amount),
         
     | 
| 
      
 202 
     | 
    
         
            +
                  #                         converter: Proc.new { |balance| balance.to_money }
         
     | 
| 
      
 203 
     | 
    
         
            +
                  #   composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
         
     | 
| 
       197 
204 
     | 
    
         
             
                  #   composed_of :gps_location
         
     | 
| 
       198 
     | 
    
         
            -
                  #   composed_of :gps_location, : 
     | 
| 
      
 205 
     | 
    
         
            +
                  #   composed_of :gps_location, allow_nil: true
         
     | 
| 
       199 
206 
     | 
    
         
             
                  #   composed_of :ip_address,
         
     | 
| 
       200 
     | 
    
         
            -
                  #               : 
     | 
| 
       201 
     | 
    
         
            -
                  #               : 
     | 
| 
       202 
     | 
    
         
            -
                  #               : 
     | 
| 
       203 
     | 
    
         
            -
                  #               : 
     | 
| 
      
 207 
     | 
    
         
            +
                  #               class_name: 'IPAddr',
         
     | 
| 
      
 208 
     | 
    
         
            +
                  #               mapping: %w(ip to_i),
         
     | 
| 
      
 209 
     | 
    
         
            +
                  #               constructor: Proc.new { |ip| IPAddr.new(ip, Socket::AF_INET) },
         
     | 
| 
      
 210 
     | 
    
         
            +
                  #               converter: Proc.new { |ip| ip.is_a?(Integer) ? IPAddr.new(ip, Socket::AF_INET) : IPAddr.new(ip.to_s) }
         
     | 
| 
       204 
211 
     | 
    
         
             
                  #
         
     | 
| 
       205 
212 
     | 
    
         
             
                  def composed_of(part_id, options = {})
         
     | 
| 
       206 
213 
     | 
    
         
             
                    options.assert_valid_keys(:class_name, :mapping, :allow_nil, :constructor, :converter)
         
     | 
| 
         @@ -216,7 +223,7 @@ module ActiveRecord 
     | 
|
| 
       216 
223 
     | 
    
         
             
                    reader_method(name, class_name, mapping, allow_nil, constructor)
         
     | 
| 
       217 
224 
     | 
    
         
             
                    writer_method(name, class_name, mapping, allow_nil, converter)
         
     | 
| 
       218 
225 
     | 
    
         | 
| 
       219 
     | 
    
         
            -
                    create_reflection(:composed_of, part_id, options, self)
         
     | 
| 
      
 226 
     | 
    
         
            +
                    create_reflection(:composed_of, part_id, nil, options, self)
         
     | 
| 
       220 
227 
     | 
    
         
             
                  end
         
     | 
| 
       221 
228 
     | 
    
         | 
| 
       222 
229 
     | 
    
         
             
                  private
         
     | 
| 
         @@ -235,16 +242,15 @@ module ActiveRecord 
     | 
|
| 
       235 
242 
     | 
    
         | 
| 
       236 
243 
     | 
    
         
             
                    def writer_method(name, class_name, mapping, allow_nil, converter)
         
     | 
| 
       237 
244 
     | 
    
         
             
                      define_method("#{name}=") do |part|
         
     | 
| 
      
 245 
     | 
    
         
            +
                        klass = class_name.constantize
         
     | 
| 
      
 246 
     | 
    
         
            +
                        unless part.is_a?(klass) || converter.nil? || part.nil?
         
     | 
| 
      
 247 
     | 
    
         
            +
                          part = converter.respond_to?(:call) ? converter.call(part) : klass.send(converter, part)
         
     | 
| 
      
 248 
     | 
    
         
            +
                        end
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
       238 
250 
     | 
    
         
             
                        if part.nil? && allow_nil
         
     | 
| 
       239 
251 
     | 
    
         
             
                          mapping.each { |pair| self[pair.first] = nil }
         
     | 
| 
       240 
252 
     | 
    
         
             
                          @aggregation_cache[name] = nil
         
     | 
| 
       241 
253 
     | 
    
         
             
                        else
         
     | 
| 
       242 
     | 
    
         
            -
                          unless part.is_a?(class_name.constantize) || converter.nil?
         
     | 
| 
       243 
     | 
    
         
            -
                            part = converter.respond_to?(:call) ?
         
     | 
| 
       244 
     | 
    
         
            -
                              converter.call(part) :
         
     | 
| 
       245 
     | 
    
         
            -
                              class_name.constantize.send(converter, part)
         
     | 
| 
       246 
     | 
    
         
            -
                          end
         
     | 
| 
       247 
     | 
    
         
            -
             
     | 
| 
       248 
254 
     | 
    
         
             
                          mapping.each { |pair| self[pair.first] = part.send(pair.last) }
         
     | 
| 
       249 
255 
     | 
    
         
             
                          @aggregation_cache[name] = part.freeze
         
     | 
| 
       250 
256 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              class AssociationRelation < Relation
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(klass, table, association)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  super(klass, table)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @association = association
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def proxy_association
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @association
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def ==(other)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  other == to_a
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                private
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def exec_queries
         
     | 
| 
      
 19 
     | 
    
         
            +
                  super.each { |r| @association.set_inverse_instance r }
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -8,7 +8,7 @@ module ActiveRecord 
     | 
|
| 
       8 
8 
     | 
    
         
             
                  attr_reader :aliases, :table_joins, :connection
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                  # table_joins is an array of arel joins which might conflict with the aliases we assign here
         
     | 
| 
       11 
     | 
    
         
            -
                  def initialize(connection =  
     | 
| 
      
 11 
     | 
    
         
            +
                  def initialize(connection = Base.connection, table_joins = [])
         
     | 
| 
       12 
12 
     | 
    
         
             
                    @aliases     = Hash.new { |h,k| h[k] = initial_count_for(k) }
         
     | 
| 
       13 
13 
     | 
    
         
             
                    @table_joins = table_joins
         
     | 
| 
       14 
14 
     | 
    
         
             
                    @connection  = connection
         
     | 
| 
         @@ -60,8 +60,10 @@ module ActiveRecord 
     | 
|
| 
       60 
60 
     | 
    
         
             
                          join.left.downcase.scan(
         
     | 
| 
       61 
61 
     | 
    
         
             
                            /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/
         
     | 
| 
       62 
62 
     | 
    
         
             
                          ).size
         
     | 
| 
       63 
     | 
    
         
            -
                         
     | 
| 
      
 63 
     | 
    
         
            +
                        elsif join.respond_to? :left
         
     | 
| 
       64 
64 
     | 
    
         
             
                          join.left.table_name == name ? 1 : 0
         
     | 
| 
      
 65 
     | 
    
         
            +
                        else
         
     | 
| 
      
 66 
     | 
    
         
            +
                          0
         
     | 
| 
       65 
67 
     | 
    
         
             
                        end
         
     | 
| 
       66 
68 
     | 
    
         
             
                      end
         
     | 
| 
       67 
69 
     | 
    
         | 
| 
         @@ -1,5 +1,4 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'active_support/core_ext/array/wrap'
         
     | 
| 
       2 
     | 
    
         
            -
            require 'active_support/core_ext/object/inclusion'
         
     | 
| 
       3 
2 
     | 
    
         | 
| 
       4 
3 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       5 
4 
     | 
    
         
             
              module Associations
         
     | 
| 
         @@ -19,34 +18,33 @@ module ActiveRecord 
     | 
|
| 
       19 
18 
     | 
    
         
             
                #         HasManyThroughAssociation + ThroughAssociation
         
     | 
| 
       20 
19 
     | 
    
         
             
                class Association #:nodoc:
         
     | 
| 
       21 
20 
     | 
    
         
             
                  attr_reader :owner, :target, :reflection
         
     | 
| 
      
 21 
     | 
    
         
            +
                  attr_accessor :inversed
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         
             
                  delegate :options, :to => :reflection
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
                  def initialize(owner, reflection)
         
     | 
| 
       26 
26 
     | 
    
         
             
                    reflection.check_validity!
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                    @target = nil
         
     | 
| 
       29 
28 
     | 
    
         
             
                    @owner, @reflection = owner, reflection
         
     | 
| 
       30 
     | 
    
         
            -
                    @updated = false
         
     | 
| 
       31 
29 
     | 
    
         | 
| 
       32 
30 
     | 
    
         
             
                    reset
         
     | 
| 
       33 
31 
     | 
    
         
             
                    reset_scope
         
     | 
| 
       34 
32 
     | 
    
         
             
                  end
         
     | 
| 
       35 
33 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                  # Returns the name of the table of the  
     | 
| 
      
 34 
     | 
    
         
            +
                  # Returns the name of the table of the associated class:
         
     | 
| 
       37 
35 
     | 
    
         
             
                  #
         
     | 
| 
       38 
36 
     | 
    
         
             
                  #   post.comments.aliased_table_name # => "comments"
         
     | 
| 
       39 
37 
     | 
    
         
             
                  #
         
     | 
| 
       40 
38 
     | 
    
         
             
                  def aliased_table_name
         
     | 
| 
       41 
     | 
    
         
            -
                     
     | 
| 
      
 39 
     | 
    
         
            +
                    klass.table_name
         
     | 
| 
       42 
40 
     | 
    
         
             
                  end
         
     | 
| 
       43 
41 
     | 
    
         | 
| 
       44 
42 
     | 
    
         
             
                  # Resets the \loaded flag to +false+ and sets the \target to +nil+.
         
     | 
| 
       45 
43 
     | 
    
         
             
                  def reset
         
     | 
| 
       46 
44 
     | 
    
         
             
                    @loaded = false
         
     | 
| 
       47 
     | 
    
         
            -
                    IdentityMap.remove(target) if IdentityMap.enabled? && target
         
     | 
| 
       48 
45 
     | 
    
         
             
                    @target = nil
         
     | 
| 
       49 
46 
     | 
    
         
             
                    @stale_state = nil
         
     | 
| 
      
 47 
     | 
    
         
            +
                    @inversed = false
         
     | 
| 
       50 
48 
     | 
    
         
             
                  end
         
     | 
| 
       51 
49 
     | 
    
         | 
| 
       52 
50 
     | 
    
         
             
                  # Reloads the \target and returns +self+ on success.
         
     | 
| 
         @@ -64,18 +62,19 @@ module ActiveRecord 
     | 
|
| 
       64 
62 
     | 
    
         | 
| 
       65 
63 
     | 
    
         
             
                  # Asserts the \target has been loaded setting the \loaded flag to +true+.
         
     | 
| 
       66 
64 
     | 
    
         
             
                  def loaded!
         
     | 
| 
       67 
     | 
    
         
            -
                    @loaded 
     | 
| 
      
 65 
     | 
    
         
            +
                    @loaded = true
         
     | 
| 
       68 
66 
     | 
    
         
             
                    @stale_state = stale_state
         
     | 
| 
      
 67 
     | 
    
         
            +
                    @inversed = false
         
     | 
| 
       69 
68 
     | 
    
         
             
                  end
         
     | 
| 
       70 
69 
     | 
    
         | 
| 
       71 
70 
     | 
    
         
             
                  # The target is stale if the target no longer points to the record(s) that the
         
     | 
| 
       72 
71 
     | 
    
         
             
                  # relevant foreign_key(s) refers to. If stale, the association accessor method
         
     | 
| 
       73 
72 
     | 
    
         
             
                  # on the owner will reload the target. It's up to subclasses to implement the
         
     | 
| 
       74 
     | 
    
         
            -
                  #  
     | 
| 
      
 73 
     | 
    
         
            +
                  # stale_state method if relevant.
         
     | 
| 
       75 
74 
     | 
    
         
             
                  #
         
     | 
| 
       76 
75 
     | 
    
         
             
                  # Note that if the target has not been loaded, it is not considered stale.
         
     | 
| 
       77 
76 
     | 
    
         
             
                  def stale_target?
         
     | 
| 
       78 
     | 
    
         
            -
                    loaded? && @stale_state != stale_state
         
     | 
| 
      
 77 
     | 
    
         
            +
                    !inversed && loaded? && @stale_state != stale_state
         
     | 
| 
       79 
78 
     | 
    
         
             
                  end
         
     | 
| 
       80 
79 
     | 
    
         | 
| 
       81 
80 
     | 
    
         
             
                  # Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
         
     | 
| 
         @@ -84,14 +83,19 @@ module ActiveRecord 
     | 
|
| 
       84 
83 
     | 
    
         
             
                    loaded!
         
     | 
| 
       85 
84 
     | 
    
         
             
                  end
         
     | 
| 
       86 
85 
     | 
    
         | 
| 
       87 
     | 
    
         
            -
                  def  
     | 
| 
      
 86 
     | 
    
         
            +
                  def scope
         
     | 
| 
       88 
87 
     | 
    
         
             
                    target_scope.merge(association_scope)
         
     | 
| 
       89 
88 
     | 
    
         
             
                  end
         
     | 
| 
       90 
89 
     | 
    
         | 
| 
      
 90 
     | 
    
         
            +
                  def scoped
         
     | 
| 
      
 91 
     | 
    
         
            +
                    ActiveSupport::Deprecation.warn "#scoped is deprecated. use #scope instead."
         
     | 
| 
      
 92 
     | 
    
         
            +
                    scope
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
       91 
95 
     | 
    
         
             
                  # The scope for this association.
         
     | 
| 
       92 
96 
     | 
    
         
             
                  #
         
     | 
| 
       93 
97 
     | 
    
         
             
                  # Note that the association_scope is merged into the target_scope only when the
         
     | 
| 
       94 
     | 
    
         
            -
                  #  
     | 
| 
      
 98 
     | 
    
         
            +
                  # scope method is called. This is because at that point the call may be surrounded
         
     | 
| 
       95 
99 
     | 
    
         
             
                  # by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
         
     | 
| 
       96 
100 
     | 
    
         
             
                  # actually gets built.
         
     | 
| 
       97 
101 
     | 
    
         
             
                  def association_scope
         
     | 
| 
         @@ -109,10 +113,11 @@ module ActiveRecord 
     | 
|
| 
       109 
113 
     | 
    
         
             
                    if record && invertible_for?(record)
         
     | 
| 
       110 
114 
     | 
    
         
             
                      inverse = record.association(inverse_reflection_for(record).name)
         
     | 
| 
       111 
115 
     | 
    
         
             
                      inverse.target = owner
         
     | 
| 
      
 116 
     | 
    
         
            +
                      inverse.inversed = true
         
     | 
| 
       112 
117 
     | 
    
         
             
                    end
         
     | 
| 
       113 
118 
     | 
    
         
             
                  end
         
     | 
| 
       114 
119 
     | 
    
         | 
| 
       115 
     | 
    
         
            -
                  #  
     | 
| 
      
 120 
     | 
    
         
            +
                  # Returns the class of the target. belongs_to polymorphic overrides this to look at the
         
     | 
| 
       116 
121 
     | 
    
         
             
                  # polymorphic_type field on the owner.
         
     | 
| 
       117 
122 
     | 
    
         
             
                  def klass
         
     | 
| 
       118 
123 
     | 
    
         
             
                    reflection.klass
         
     | 
| 
         @@ -121,7 +126,11 @@ module ActiveRecord 
     | 
|
| 
       121 
126 
     | 
    
         
             
                  # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
         
     | 
| 
       122 
127 
     | 
    
         
             
                  # through association's scope)
         
     | 
| 
       123 
128 
     | 
    
         
             
                  def target_scope
         
     | 
| 
       124 
     | 
    
         
            -
                    klass. 
     | 
| 
      
 129 
     | 
    
         
            +
                    all = klass.all
         
     | 
| 
      
 130 
     | 
    
         
            +
                    scope = AssociationRelation.new(klass, klass.arel_table, self)
         
     | 
| 
      
 131 
     | 
    
         
            +
                    scope.merge! all
         
     | 
| 
      
 132 
     | 
    
         
            +
                    scope.default_scoped = all.default_scoped?
         
     | 
| 
      
 133 
     | 
    
         
            +
                    scope
         
     | 
| 
       125 
134 
     | 
    
         
             
                  end
         
     | 
| 
       126 
135 
     | 
    
         | 
| 
       127 
136 
     | 
    
         
             
                  # Loads the \target if needed and returns it.
         
     | 
| 
         @@ -129,28 +138,14 @@ module ActiveRecord 
     | 
|
| 
       129 
138 
     | 
    
         
             
                  # This method is abstract in the sense that it relies on +find_target+,
         
     | 
| 
       130 
139 
     | 
    
         
             
                  # which is expected to be provided by descendants.
         
     | 
| 
       131 
140 
     | 
    
         
             
                  #
         
     | 
| 
       132 
     | 
    
         
            -
                  # If the \target is  
     | 
| 
       133 
     | 
    
         
            -
                  #  
     | 
| 
       134 
     | 
    
         
            -
                  #
         
     | 
| 
       135 
     | 
    
         
            -
                  # Otherwise if the \target is already \loaded it is just returned. Thus, you can
         
     | 
| 
       136 
     | 
    
         
            -
                  # call +load_target+ unconditionally to get the \target.
         
     | 
| 
      
 141 
     | 
    
         
            +
                  # If the \target is already \loaded it is just returned. Thus, you can call
         
     | 
| 
      
 142 
     | 
    
         
            +
                  # +load_target+ unconditionally to get the \target.
         
     | 
| 
       137 
143 
     | 
    
         
             
                  #
         
     | 
| 
       138 
144 
     | 
    
         
             
                  # ActiveRecord::RecordNotFound is rescued within the method, and it is
         
     | 
| 
       139 
145 
     | 
    
         
             
                  # not reraised. The proxy is \reset and +nil+ is the return value.
         
     | 
| 
       140 
146 
     | 
    
         
             
                  def load_target
         
     | 
| 
       141 
     | 
    
         
            -
                    if (@stale_state && stale_target?) || find_target?
         
     | 
| 
       142 
     | 
    
         
            -
             
     | 
| 
       143 
     | 
    
         
            -
                        if IdentityMap.enabled? && association_class && association_class.respond_to?(:base_class)
         
     | 
| 
       144 
     | 
    
         
            -
                          @target = IdentityMap.get(association_class, owner[reflection.foreign_key])
         
     | 
| 
       145 
     | 
    
         
            -
                        elsif @stale_state && stale_target?
         
     | 
| 
       146 
     | 
    
         
            -
                          @target = find_target
         
     | 
| 
       147 
     | 
    
         
            -
                        end
         
     | 
| 
       148 
     | 
    
         
            -
                      rescue NameError
         
     | 
| 
       149 
     | 
    
         
            -
                        nil
         
     | 
| 
       150 
     | 
    
         
            -
                      ensure
         
     | 
| 
       151 
     | 
    
         
            -
                        @target ||= find_target
         
     | 
| 
       152 
     | 
    
         
            -
                      end
         
     | 
| 
       153 
     | 
    
         
            -
                    end
         
     | 
| 
      
 147 
     | 
    
         
            +
                    @target = find_target if (@stale_state && stale_target?) || find_target?
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
       154 
149 
     | 
    
         
             
                    loaded! unless loaded?
         
     | 
| 
       155 
150 
     | 
    
         
             
                    target
         
     | 
| 
       156 
151 
     | 
    
         
             
                  rescue ActiveRecord::RecordNotFound
         
     | 
| 
         @@ -159,12 +154,31 @@ module ActiveRecord 
     | 
|
| 
       159 
154 
     | 
    
         | 
| 
       160 
155 
     | 
    
         
             
                  def interpolate(sql, record = nil)
         
     | 
| 
       161 
156 
     | 
    
         
             
                    if sql.respond_to?(:to_proc)
         
     | 
| 
       162 
     | 
    
         
            -
                      owner. 
     | 
| 
      
 157 
     | 
    
         
            +
                      owner.instance_exec(record, &sql)
         
     | 
| 
       163 
158 
     | 
    
         
             
                    else
         
     | 
| 
       164 
159 
     | 
    
         
             
                      sql
         
     | 
| 
       165 
160 
     | 
    
         
             
                    end
         
     | 
| 
       166 
161 
     | 
    
         
             
                  end
         
     | 
| 
       167 
162 
     | 
    
         | 
| 
      
 163 
     | 
    
         
            +
                  # We can't dump @reflection since it contains the scope proc
         
     | 
| 
      
 164 
     | 
    
         
            +
                  def marshal_dump
         
     | 
| 
      
 165 
     | 
    
         
            +
                    ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
         
     | 
| 
      
 166 
     | 
    
         
            +
                    [@reflection.name, ivars]
         
     | 
| 
      
 167 
     | 
    
         
            +
                  end
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                  def marshal_load(data)
         
     | 
| 
      
 170 
     | 
    
         
            +
                    reflection_name, ivars = data
         
     | 
| 
      
 171 
     | 
    
         
            +
                    ivars.each { |name, val| instance_variable_set(name, val) }
         
     | 
| 
      
 172 
     | 
    
         
            +
                    @reflection = @owner.class.reflect_on_association(reflection_name)
         
     | 
| 
      
 173 
     | 
    
         
            +
                  end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                  def initialize_attributes(record) #:nodoc:
         
     | 
| 
      
 176 
     | 
    
         
            +
                    skip_assign = [reflection.foreign_key, reflection.type].compact
         
     | 
| 
      
 177 
     | 
    
         
            +
                    attributes = create_scope.except(*(record.changed - skip_assign))
         
     | 
| 
      
 178 
     | 
    
         
            +
                    record.assign_attributes(attributes)
         
     | 
| 
      
 179 
     | 
    
         
            +
                    set_inverse_instance(record)
         
     | 
| 
      
 180 
     | 
    
         
            +
                  end
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
       168 
182 
     | 
    
         
             
                  private
         
     | 
| 
       169 
183 
     | 
    
         | 
| 
       170 
184 
     | 
    
         
             
                    def find_target?
         
     | 
| 
         @@ -174,7 +188,7 @@ module ActiveRecord 
     | 
|
| 
       174 
188 
     | 
    
         
             
                    def creation_attributes
         
     | 
| 
       175 
189 
     | 
    
         
             
                      attributes = {}
         
     | 
| 
       176 
190 
     | 
    
         | 
| 
       177 
     | 
    
         
            -
                      if reflection.macro 
     | 
| 
      
 191 
     | 
    
         
            +
                      if (reflection.macro == :has_one || reflection.macro == :has_many) && !options[:through]
         
     | 
| 
       178 
192 
     | 
    
         
             
                        attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
         
     | 
| 
       179 
193 
     | 
    
         | 
| 
       180 
194 
     | 
    
         
             
                        if reflection.options[:as]
         
     | 
| 
         @@ -204,7 +218,7 @@ module ActiveRecord 
     | 
|
| 
       204 
218 
     | 
    
         
             
                    # Raises ActiveRecord::AssociationTypeMismatch unless +record+ is of
         
     | 
| 
       205 
219 
     | 
    
         
             
                    # the kind of the class of the associated objects. Meant to be used as
         
     | 
| 
       206 
220 
     | 
    
         
             
                    # a sanity check when you are about to assign an associated record.
         
     | 
| 
       207 
     | 
    
         
            -
                    def raise_on_type_mismatch(record)
         
     | 
| 
      
 221 
     | 
    
         
            +
                    def raise_on_type_mismatch!(record)
         
     | 
| 
       208 
222 
     | 
    
         
             
                      unless record.is_a?(reflection.klass) || record.is_a?(reflection.class_name.constantize)
         
     | 
| 
       209 
223 
     | 
    
         
             
                        message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
         
     | 
| 
       210 
224 
     | 
    
         
             
                        raise ActiveRecord::AssociationTypeMismatch, message
         
     | 
| 
         @@ -218,28 +232,28 @@ module ActiveRecord 
     | 
|
| 
       218 
232 
     | 
    
         
             
                      reflection.inverse_of
         
     | 
| 
       219 
233 
     | 
    
         
             
                    end
         
     | 
| 
       220 
234 
     | 
    
         | 
| 
       221 
     | 
    
         
            -
                    #  
     | 
| 
      
 235 
     | 
    
         
            +
                    # Returns true if inverse association on the given record needs to be set.
         
     | 
| 
      
 236 
     | 
    
         
            +
                    # This method is redefined by subclasses.
         
     | 
| 
       222 
237 
     | 
    
         
             
                    def invertible_for?(record)
         
     | 
| 
       223 
     | 
    
         
            -
                      inverse_reflection_for(record)
         
     | 
| 
      
 238 
     | 
    
         
            +
                      foreign_key_for?(record) && inverse_reflection_for(record)
         
     | 
| 
      
 239 
     | 
    
         
            +
                    end
         
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
      
 241 
     | 
    
         
            +
                    # Returns true if record contains the foreign_key
         
     | 
| 
      
 242 
     | 
    
         
            +
                    def foreign_key_for?(record)
         
     | 
| 
      
 243 
     | 
    
         
            +
                      record.has_attribute?(reflection.foreign_key)
         
     | 
| 
       224 
244 
     | 
    
         
             
                    end
         
     | 
| 
       225 
245 
     | 
    
         | 
| 
       226 
246 
     | 
    
         
             
                    # This should be implemented to return the values of the relevant key(s) on the owner,
         
     | 
| 
       227 
     | 
    
         
            -
                    # so that when  
     | 
| 
      
 247 
     | 
    
         
            +
                    # so that when stale_state is different from the value stored on the last find_target,
         
     | 
| 
       228 
248 
     | 
    
         
             
                    # the target is stale.
         
     | 
| 
       229 
249 
     | 
    
         
             
                    #
         
     | 
| 
       230 
250 
     | 
    
         
             
                    # This is only relevant to certain associations, which is why it returns nil by default.
         
     | 
| 
       231 
251 
     | 
    
         
             
                    def stale_state
         
     | 
| 
       232 
252 
     | 
    
         
             
                    end
         
     | 
| 
       233 
253 
     | 
    
         | 
| 
       234 
     | 
    
         
            -
                    def  
     | 
| 
       235 
     | 
    
         
            -
                       
     | 
| 
       236 
     | 
    
         
            -
             
     | 
| 
       237 
     | 
    
         
            -
             
     | 
| 
       238 
     | 
    
         
            -
                    def build_record(attributes, options)
         
     | 
| 
       239 
     | 
    
         
            -
                      reflection.build_association(attributes, options) do |record|
         
     | 
| 
       240 
     | 
    
         
            -
                        skip_assign = [reflection.foreign_key, reflection.type].compact
         
     | 
| 
       241 
     | 
    
         
            -
                        attributes = create_scope.except(*(record.changed - skip_assign))
         
     | 
| 
       242 
     | 
    
         
            -
                        record.assign_attributes(attributes, :without_protection => true)
         
     | 
| 
      
 254 
     | 
    
         
            +
                    def build_record(attributes)
         
     | 
| 
      
 255 
     | 
    
         
            +
                      reflection.build_association(attributes) do |record|
         
     | 
| 
      
 256 
     | 
    
         
            +
                        initialize_attributes(record)
         
     | 
| 
       243 
257 
     | 
    
         
             
                      end
         
     | 
| 
       244 
258 
     | 
    
         
             
                    end
         
     | 
| 
       245 
259 
     | 
    
         
             
                end
         
     |