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
 
| 
         @@ -1,13 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'active_support/core_ext/enumerable'
         
     | 
| 
       2 
     | 
    
         
            -
            require ' 
     | 
| 
      
 2 
     | 
    
         
            +
            require 'mutex_m'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       5 
5 
     | 
    
         
             
              # = Active Record Attribute Methods
         
     | 
| 
       6 
     | 
    
         
            -
              module AttributeMethods 
     | 
| 
      
 6 
     | 
    
         
            +
              module AttributeMethods
         
     | 
| 
       7 
7 
     | 
    
         
             
                extend ActiveSupport::Concern
         
     | 
| 
       8 
8 
     | 
    
         
             
                include ActiveModel::AttributeMethods
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                included do
         
     | 
| 
      
 11 
     | 
    
         
            +
                  initialize_generated_modules
         
     | 
| 
       11 
12 
     | 
    
         
             
                  include Read
         
     | 
| 
       12 
13 
     | 
    
         
             
                  include Write
         
     | 
| 
       13 
14 
     | 
    
         
             
                  include BeforeTypeCast
         
     | 
| 
         @@ -16,79 +17,69 @@ module ActiveRecord 
     | 
|
| 
       16 
17 
     | 
    
         
             
                  include TimeZoneConversion
         
     | 
| 
       17 
18 
     | 
    
         
             
                  include Dirty
         
     | 
| 
       18 
19 
     | 
    
         
             
                  include Serialization
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
       20 
21 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                   
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                    read_attribute(attr_name)
         
     | 
| 
      
 22 
     | 
    
         
            +
                module ClassMethods
         
     | 
| 
      
 23 
     | 
    
         
            +
                  def inherited(child_class) #:nodoc:
         
     | 
| 
      
 24 
     | 
    
         
            +
                    child_class.initialize_generated_modules
         
     | 
| 
      
 25 
     | 
    
         
            +
                    super
         
     | 
| 
       26 
26 
     | 
    
         
             
                  end
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                   
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def initialize_generated_modules # :nodoc:
         
     | 
| 
      
 29 
     | 
    
         
            +
                    @generated_attribute_methods = Module.new {
         
     | 
| 
      
 30 
     | 
    
         
            +
                      extend Mutex_m
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                      const_set :AttrNames, Module.new {
         
     | 
| 
      
 33 
     | 
    
         
            +
                        def self.set_name_cache(name, value)
         
     | 
| 
      
 34 
     | 
    
         
            +
                          const_name = "ATTR_#{name}"
         
     | 
| 
      
 35 
     | 
    
         
            +
                          unless const_defined? const_name
         
     | 
| 
      
 36 
     | 
    
         
            +
                            const_set const_name, value.dup.freeze
         
     | 
| 
      
 37 
     | 
    
         
            +
                          end
         
     | 
| 
      
 38 
     | 
    
         
            +
                        end
         
     | 
| 
      
 39 
     | 
    
         
            +
                      }
         
     | 
| 
      
 40 
     | 
    
         
            +
                    }
         
     | 
| 
      
 41 
     | 
    
         
            +
                    @attribute_methods_generated = false
         
     | 
| 
      
 42 
     | 
    
         
            +
                    include @generated_attribute_methods
         
     | 
| 
       32 
43 
     | 
    
         
             
                  end
         
     | 
| 
       33 
     | 
    
         
            -
                end
         
     | 
| 
       34 
44 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                module ClassMethods
         
     | 
| 
       36 
45 
     | 
    
         
             
                  # Generates all the attribute related methods for columns in the database
         
     | 
| 
       37 
46 
     | 
    
         
             
                  # accessors, mutators and query methods.
         
     | 
| 
       38 
     | 
    
         
            -
                  def define_attribute_methods
         
     | 
| 
       39 
     | 
    
         
            -
                     
     | 
| 
       40 
     | 
    
         
            -
                      msg = "It looks like something (probably a gem/plugin) is overriding the " \
         
     | 
| 
       41 
     | 
    
         
            -
                            "ActiveRecord::Base.inherited method. It is important that this hook executes so " \
         
     | 
| 
       42 
     | 
    
         
            -
                            "that your models are set up correctly. A workaround has been added to stop this " \
         
     | 
| 
       43 
     | 
    
         
            -
                            "causing an error in 3.2, but future versions will simply not work if the hook is " \
         
     | 
| 
       44 
     | 
    
         
            -
                            "overridden. If you are using Kaminari, please upgrade as it is known to have had " \
         
     | 
| 
       45 
     | 
    
         
            -
                            "this problem.\n\n"
         
     | 
| 
       46 
     | 
    
         
            -
                      msg << "The following may help track down the problem:"
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
                      meth = method(:inherited)
         
     | 
| 
       49 
     | 
    
         
            -
                      if meth.respond_to?(:source_location)
         
     | 
| 
       50 
     | 
    
         
            -
                        msg << " #{meth.source_location.inspect}"
         
     | 
| 
       51 
     | 
    
         
            -
                      else
         
     | 
| 
       52 
     | 
    
         
            -
                        msg << " #{meth.inspect}"
         
     | 
| 
       53 
     | 
    
         
            -
                      end
         
     | 
| 
       54 
     | 
    
         
            -
                      msg << "\n\n"
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
                      ActiveSupport::Deprecation.warn(msg)
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
                      @attribute_methods_mutex = Mutex.new
         
     | 
| 
       59 
     | 
    
         
            -
                    end
         
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                    # Use a mutex; we don't want two thread simaltaneously trying to define
         
     | 
| 
      
 47 
     | 
    
         
            +
                  def define_attribute_methods # :nodoc:
         
     | 
| 
      
 48 
     | 
    
         
            +
                    # Use a mutex; we don't want two thread simultaneously trying to define
         
     | 
| 
       62 
49 
     | 
    
         
             
                    # attribute methods.
         
     | 
| 
       63 
     | 
    
         
            -
                     
     | 
| 
       64 
     | 
    
         
            -
                      return if attribute_methods_generated 
     | 
| 
      
 50 
     | 
    
         
            +
                    generated_attribute_methods.synchronize do
         
     | 
| 
      
 51 
     | 
    
         
            +
                      return false if @attribute_methods_generated
         
     | 
| 
       65 
52 
     | 
    
         
             
                      superclass.define_attribute_methods unless self == base_class
         
     | 
| 
       66 
53 
     | 
    
         
             
                      super(column_names)
         
     | 
| 
       67 
     | 
    
         
            -
                      column_names.each { |name| define_external_attribute_method(name) }
         
     | 
| 
       68 
54 
     | 
    
         
             
                      @attribute_methods_generated = true
         
     | 
| 
       69 
55 
     | 
    
         
             
                    end
         
     | 
| 
      
 56 
     | 
    
         
            +
                    true
         
     | 
| 
       70 
57 
     | 
    
         
             
                  end
         
     | 
| 
       71 
58 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                  def  
     | 
| 
       73 
     | 
    
         
            -
                     
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
                  # methods. This allows us to use method_defined? to check if the method exists,
         
     | 
| 
       78 
     | 
    
         
            -
                  # which is fast and won't give any false positives from the ancestors (because
         
     | 
| 
       79 
     | 
    
         
            -
                  # there are no ancestors).
         
     | 
| 
       80 
     | 
    
         
            -
                  def generated_external_attribute_methods
         
     | 
| 
       81 
     | 
    
         
            -
                    @generated_external_attribute_methods ||= Module.new { extend self }
         
     | 
| 
       82 
     | 
    
         
            -
                  end
         
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
                  def undefine_attribute_methods
         
     | 
| 
       85 
     | 
    
         
            -
                    super
         
     | 
| 
       86 
     | 
    
         
            -
                    @attribute_methods_generated = false
         
     | 
| 
      
 59 
     | 
    
         
            +
                  def undefine_attribute_methods # :nodoc:
         
     | 
| 
      
 60 
     | 
    
         
            +
                    generated_attribute_methods.synchronize do
         
     | 
| 
      
 61 
     | 
    
         
            +
                      super if @attribute_methods_generated
         
     | 
| 
      
 62 
     | 
    
         
            +
                      @attribute_methods_generated = false
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
       87 
64 
     | 
    
         
             
                  end
         
     | 
| 
       88 
65 
     | 
    
         | 
| 
      
 66 
     | 
    
         
            +
                  # Raises a <tt>ActiveRecord::DangerousAttributeError</tt> exception when an
         
     | 
| 
      
 67 
     | 
    
         
            +
                  # \Active \Record method is defined in the model, otherwise +false+.
         
     | 
| 
      
 68 
     | 
    
         
            +
                  #
         
     | 
| 
      
 69 
     | 
    
         
            +
                  #   class Person < ActiveRecord::Base
         
     | 
| 
      
 70 
     | 
    
         
            +
                  #     def save
         
     | 
| 
      
 71 
     | 
    
         
            +
                  #       'already defined by Active Record'
         
     | 
| 
      
 72 
     | 
    
         
            +
                  #     end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 74 
     | 
    
         
            +
                  #
         
     | 
| 
      
 75 
     | 
    
         
            +
                  #   Person.instance_method_already_implemented?(:save)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  #   # => ActiveRecord::DangerousAttributeError: save is defined by ActiveRecord
         
     | 
| 
      
 77 
     | 
    
         
            +
                  #
         
     | 
| 
      
 78 
     | 
    
         
            +
                  #   Person.instance_method_already_implemented?(:name)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  #   # => false
         
     | 
| 
       89 
80 
     | 
    
         
             
                  def instance_method_already_implemented?(method_name)
         
     | 
| 
       90 
81 
     | 
    
         
             
                    if dangerous_attribute_method?(method_name)
         
     | 
| 
       91 
     | 
    
         
            -
                      raise DangerousAttributeError, "#{method_name} is defined by  
     | 
| 
      
 82 
     | 
    
         
            +
                      raise DangerousAttributeError, "#{method_name} is defined by Active Record"
         
     | 
| 
       92 
83 
     | 
    
         
             
                    end
         
     | 
| 
       93 
84 
     | 
    
         | 
| 
       94 
85 
     | 
    
         
             
                    if superclass == Base
         
     | 
| 
         @@ -96,17 +87,18 @@ module ActiveRecord 
     | 
|
| 
       96 
87 
     | 
    
         
             
                    else
         
     | 
| 
       97 
88 
     | 
    
         
             
                      # If B < A and A defines its own attribute method, then we don't want to overwrite that.
         
     | 
| 
       98 
89 
     | 
    
         
             
                      defined = method_defined_within?(method_name, superclass, superclass.generated_attribute_methods)
         
     | 
| 
       99 
     | 
    
         
            -
                       
     | 
| 
      
 90 
     | 
    
         
            +
                      base_defined = Base.method_defined?(method_name) || Base.private_method_defined?(method_name)
         
     | 
| 
      
 91 
     | 
    
         
            +
                      defined && !base_defined || super
         
     | 
| 
       100 
92 
     | 
    
         
             
                    end
         
     | 
| 
       101 
93 
     | 
    
         
             
                  end
         
     | 
| 
       102 
94 
     | 
    
         | 
| 
       103 
95 
     | 
    
         
             
                  # A method name is 'dangerous' if it is already defined by Active Record, but
         
     | 
| 
       104 
96 
     | 
    
         
             
                  # not by any ancestors. (So 'puts' is not dangerous but 'save' is.)
         
     | 
| 
       105 
     | 
    
         
            -
                  def dangerous_attribute_method?(name)
         
     | 
| 
      
 97 
     | 
    
         
            +
                  def dangerous_attribute_method?(name) # :nodoc:
         
     | 
| 
       106 
98 
     | 
    
         
             
                    method_defined_within?(name, Base)
         
     | 
| 
       107 
99 
     | 
    
         
             
                  end
         
     | 
| 
       108 
100 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
                  def method_defined_within?(name, klass, sup = klass.superclass)
         
     | 
| 
      
 101 
     | 
    
         
            +
                  def method_defined_within?(name, klass, sup = klass.superclass) # :nodoc:
         
     | 
| 
       110 
102 
     | 
    
         
             
                    if klass.method_defined?(name) || klass.private_method_defined?(name)
         
     | 
| 
       111 
103 
     | 
    
         
             
                      if sup.method_defined?(name) || sup.private_method_defined?(name)
         
     | 
| 
       112 
104 
     | 
    
         
             
                        klass.instance_method(name).owner != sup.instance_method(name).owner
         
     | 
| 
         @@ -118,13 +110,37 @@ module ActiveRecord 
     | 
|
| 
       118 
110 
     | 
    
         
             
                    end
         
     | 
| 
       119 
111 
     | 
    
         
             
                  end
         
     | 
| 
       120 
112 
     | 
    
         | 
| 
      
 113 
     | 
    
         
            +
                  def find_generated_attribute_method(method_name) # :nodoc:
         
     | 
| 
      
 114 
     | 
    
         
            +
                    klass = self
         
     | 
| 
      
 115 
     | 
    
         
            +
                    until klass == Base
         
     | 
| 
      
 116 
     | 
    
         
            +
                      gen_methods = klass.generated_attribute_methods
         
     | 
| 
      
 117 
     | 
    
         
            +
                      return gen_methods.instance_method(method_name) if method_defined_within?(method_name, gen_methods, Object)
         
     | 
| 
      
 118 
     | 
    
         
            +
                      klass = klass.superclass
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                  # Returns +true+ if +attribute+ is an attribute method and table exists,
         
     | 
| 
      
 124 
     | 
    
         
            +
                  # +false+ otherwise.
         
     | 
| 
      
 125 
     | 
    
         
            +
                  #
         
     | 
| 
      
 126 
     | 
    
         
            +
                  #   class Person < ActiveRecord::Base
         
     | 
| 
      
 127 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 128 
     | 
    
         
            +
                  #
         
     | 
| 
      
 129 
     | 
    
         
            +
                  #   Person.attribute_method?('name')   # => true
         
     | 
| 
      
 130 
     | 
    
         
            +
                  #   Person.attribute_method?(:age=)    # => true
         
     | 
| 
      
 131 
     | 
    
         
            +
                  #   Person.attribute_method?(:nothing) # => false
         
     | 
| 
       121 
132 
     | 
    
         
             
                  def attribute_method?(attribute)
         
     | 
| 
       122 
133 
     | 
    
         
             
                    super || (table_exists? && column_names.include?(attribute.to_s.sub(/=$/, '')))
         
     | 
| 
       123 
134 
     | 
    
         
             
                  end
         
     | 
| 
       124 
135 
     | 
    
         | 
| 
       125 
     | 
    
         
            -
                  # Returns an array of column names as strings if it's not
         
     | 
| 
       126 
     | 
    
         
            -
                  #  
     | 
| 
       127 
     | 
    
         
            -
                  # 
     | 
| 
      
 136 
     | 
    
         
            +
                  # Returns an array of column names as strings if it's not an abstract class and
         
     | 
| 
      
 137 
     | 
    
         
            +
                  # table exists. Otherwise it returns an empty array.
         
     | 
| 
      
 138 
     | 
    
         
            +
                  #
         
     | 
| 
      
 139 
     | 
    
         
            +
                  #   class Person < ActiveRecord::Base
         
     | 
| 
      
 140 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 141 
     | 
    
         
            +
                  #
         
     | 
| 
      
 142 
     | 
    
         
            +
                  #   Person.attribute_names
         
     | 
| 
      
 143 
     | 
    
         
            +
                  #   # => ["id", "created_at", "updated_at", "name", "age"]
         
     | 
| 
       128 
144 
     | 
    
         
             
                  def attribute_names
         
     | 
| 
       129 
145 
     | 
    
         
             
                    @attribute_names ||= if !abstract_class? && table_exists?
         
     | 
| 
       130 
146 
     | 
    
         
             
                        column_names
         
     | 
| 
         @@ -136,21 +152,24 @@ module ActiveRecord 
     | 
|
| 
       136 
152 
     | 
    
         | 
| 
       137 
153 
     | 
    
         
             
                # If we haven't generated any methods yet, generate them, then
         
     | 
| 
       138 
154 
     | 
    
         
             
                # see if we've created the method we're looking for.
         
     | 
| 
       139 
     | 
    
         
            -
                def method_missing(method, *args, &block)
         
     | 
| 
       140 
     | 
    
         
            -
                   
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
             
     | 
| 
       143 
     | 
    
         
            -
                     
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
      
 155 
     | 
    
         
            +
                def method_missing(method, *args, &block) # :nodoc:
         
     | 
| 
      
 156 
     | 
    
         
            +
                  self.class.define_attribute_methods
         
     | 
| 
      
 157 
     | 
    
         
            +
                  if respond_to_without_attributes?(method)
         
     | 
| 
      
 158 
     | 
    
         
            +
                    # make sure to invoke the correct attribute method, as we might have gotten here via a `super`
         
     | 
| 
      
 159 
     | 
    
         
            +
                    # call in a overwritten attribute method
         
     | 
| 
      
 160 
     | 
    
         
            +
                    if attribute_method = self.class.find_generated_attribute_method(method)
         
     | 
| 
      
 161 
     | 
    
         
            +
                      # this is probably horribly slow, but should only happen at most once for a given AR class
         
     | 
| 
      
 162 
     | 
    
         
            +
                      attribute_method.bind(self).call(*args, &block)
         
     | 
| 
       145 
163 
     | 
    
         
             
                    else
         
     | 
| 
       146 
     | 
    
         
            -
                      super
         
     | 
| 
      
 164 
     | 
    
         
            +
                      return super unless respond_to_missing?(method, true)
         
     | 
| 
      
 165 
     | 
    
         
            +
                      send(method, *args, &block)
         
     | 
| 
       147 
166 
     | 
    
         
             
                    end
         
     | 
| 
       148 
167 
     | 
    
         
             
                  else
         
     | 
| 
       149 
168 
     | 
    
         
             
                    super
         
     | 
| 
       150 
169 
     | 
    
         
             
                  end
         
     | 
| 
       151 
170 
     | 
    
         
             
                end
         
     | 
| 
       152 
171 
     | 
    
         | 
| 
       153 
     | 
    
         
            -
                def attribute_missing(match, *args, &block)
         
     | 
| 
      
 172 
     | 
    
         
            +
                def attribute_missing(match, *args, &block) # :nodoc:
         
     | 
| 
       154 
173 
     | 
    
         
             
                  if self.class.columns_hash[match.attr_name]
         
     | 
| 
       155 
174 
     | 
    
         
             
                    ActiveSupport::Deprecation.warn(
         
     | 
| 
       156 
175 
     | 
    
         
             
                      "The method `#{match.method_name}', matching the attribute `#{match.attr_name}' has " \
         
     | 
| 
         @@ -164,26 +183,83 @@ module ActiveRecord 
     | 
|
| 
       164 
183 
     | 
    
         
             
                  super
         
     | 
| 
       165 
184 
     | 
    
         
             
                end
         
     | 
| 
       166 
185 
     | 
    
         | 
| 
      
 186 
     | 
    
         
            +
                # A Person object with a name attribute can ask <tt>person.respond_to?(:name)</tt>,
         
     | 
| 
      
 187 
     | 
    
         
            +
                # <tt>person.respond_to?(:name=)</tt>, and <tt>person.respond_to?(:name?)</tt>
         
     | 
| 
      
 188 
     | 
    
         
            +
                # which will all return +true+. It also define the attribute methods if they have
         
     | 
| 
      
 189 
     | 
    
         
            +
                # not been generated.
         
     | 
| 
      
 190 
     | 
    
         
            +
                #
         
     | 
| 
      
 191 
     | 
    
         
            +
                #   class Person < ActiveRecord::Base
         
     | 
| 
      
 192 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 193 
     | 
    
         
            +
                #
         
     | 
| 
      
 194 
     | 
    
         
            +
                #   person = Person.new
         
     | 
| 
      
 195 
     | 
    
         
            +
                #   person.respond_to(:name)    # => true
         
     | 
| 
      
 196 
     | 
    
         
            +
                #   person.respond_to(:name=)   # => true
         
     | 
| 
      
 197 
     | 
    
         
            +
                #   person.respond_to(:name?)   # => true
         
     | 
| 
      
 198 
     | 
    
         
            +
                #   person.respond_to('age')    # => true
         
     | 
| 
      
 199 
     | 
    
         
            +
                #   person.respond_to('age=')   # => true
         
     | 
| 
      
 200 
     | 
    
         
            +
                #   person.respond_to('age?')   # => true
         
     | 
| 
      
 201 
     | 
    
         
            +
                #   person.respond_to(:nothing) # => false
         
     | 
| 
       167 
202 
     | 
    
         
             
                def respond_to?(name, include_private = false)
         
     | 
| 
       168 
     | 
    
         
            -
                   
     | 
| 
       169 
     | 
    
         
            -
                   
     | 
| 
      
 203 
     | 
    
         
            +
                  name = name.to_s
         
     | 
| 
      
 204 
     | 
    
         
            +
                  self.class.define_attribute_methods
         
     | 
| 
      
 205 
     | 
    
         
            +
                  result = super
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                  # If the result is false the answer is false.
         
     | 
| 
      
 208 
     | 
    
         
            +
                  return false unless result
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                  # If the result is true then check for the select case.
         
     | 
| 
      
 211 
     | 
    
         
            +
                  # For queries selecting a subset of columns, return false for unselected columns.
         
     | 
| 
      
 212 
     | 
    
         
            +
                  # We check defined?(@attributes) not to issue warnings if called on objects that
         
     | 
| 
      
 213 
     | 
    
         
            +
                  # have been allocated but not yet initialized.
         
     | 
| 
      
 214 
     | 
    
         
            +
                  if defined?(@attributes) && @attributes.present? && self.class.column_names.include?(name)
         
     | 
| 
      
 215 
     | 
    
         
            +
                    return has_attribute?(name)
         
     | 
| 
      
 216 
     | 
    
         
            +
                  end
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
                  return true
         
     | 
| 
       170 
219 
     | 
    
         
             
                end
         
     | 
| 
       171 
220 
     | 
    
         | 
| 
       172 
     | 
    
         
            -
                # Returns true if the given attribute is in the attributes hash
         
     | 
| 
      
 221 
     | 
    
         
            +
                # Returns +true+ if the given attribute is in the attributes hash, otherwise +false+.
         
     | 
| 
      
 222 
     | 
    
         
            +
                #
         
     | 
| 
      
 223 
     | 
    
         
            +
                #   class Person < ActiveRecord::Base
         
     | 
| 
      
 224 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 225 
     | 
    
         
            +
                #
         
     | 
| 
      
 226 
     | 
    
         
            +
                #   person = Person.new
         
     | 
| 
      
 227 
     | 
    
         
            +
                #   person.has_attribute?(:name)    # => true
         
     | 
| 
      
 228 
     | 
    
         
            +
                #   person.has_attribute?('age')    # => true
         
     | 
| 
      
 229 
     | 
    
         
            +
                #   person.has_attribute?(:nothing) # => false
         
     | 
| 
       173 
230 
     | 
    
         
             
                def has_attribute?(attr_name)
         
     | 
| 
       174 
231 
     | 
    
         
             
                  @attributes.has_key?(attr_name.to_s)
         
     | 
| 
       175 
232 
     | 
    
         
             
                end
         
     | 
| 
       176 
233 
     | 
    
         | 
| 
       177 
234 
     | 
    
         
             
                # Returns an array of names for the attributes available on this object.
         
     | 
| 
      
 235 
     | 
    
         
            +
                #
         
     | 
| 
      
 236 
     | 
    
         
            +
                #   class Person < ActiveRecord::Base
         
     | 
| 
      
 237 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 238 
     | 
    
         
            +
                #
         
     | 
| 
      
 239 
     | 
    
         
            +
                #   person = Person.new
         
     | 
| 
      
 240 
     | 
    
         
            +
                #   person.attribute_names
         
     | 
| 
      
 241 
     | 
    
         
            +
                #   # => ["id", "created_at", "updated_at", "name", "age"]
         
     | 
| 
       178 
242 
     | 
    
         
             
                def attribute_names
         
     | 
| 
       179 
243 
     | 
    
         
             
                  @attributes.keys
         
     | 
| 
       180 
244 
     | 
    
         
             
                end
         
     | 
| 
       181 
245 
     | 
    
         | 
| 
       182 
246 
     | 
    
         
             
                # Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
         
     | 
| 
      
 247 
     | 
    
         
            +
                #
         
     | 
| 
      
 248 
     | 
    
         
            +
                #   class Person < ActiveRecord::Base
         
     | 
| 
      
 249 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 250 
     | 
    
         
            +
                #
         
     | 
| 
      
 251 
     | 
    
         
            +
                #   person = Person.create(name: 'Francesco', age: 22)
         
     | 
| 
      
 252 
     | 
    
         
            +
                #   person.attributes
         
     | 
| 
      
 253 
     | 
    
         
            +
                #   # => {"id"=>3, "created_at"=>Sun, 21 Oct 2012 04:53:04, "updated_at"=>Sun, 21 Oct 2012 04:53:04, "name"=>"Francesco", "age"=>22}
         
     | 
| 
       183 
254 
     | 
    
         
             
                def attributes
         
     | 
| 
       184 
     | 
    
         
            -
                   
     | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
       186 
     | 
    
         
            -
                   
     | 
| 
      
 255 
     | 
    
         
            +
                  attribute_names.each_with_object({}) { |name, attrs|
         
     | 
| 
      
 256 
     | 
    
         
            +
                    attrs[name] = read_attribute(name)
         
     | 
| 
      
 257 
     | 
    
         
            +
                  }
         
     | 
| 
      
 258 
     | 
    
         
            +
                end
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
                # Placeholder so it can be overriden when needed by serialization
         
     | 
| 
      
 261 
     | 
    
         
            +
                def attributes_for_coder # :nodoc:
         
     | 
| 
      
 262 
     | 
    
         
            +
                  attributes
         
     | 
| 
       187 
263 
     | 
    
         
             
                end
         
     | 
| 
       188 
264 
     | 
    
         | 
| 
       189 
265 
     | 
    
         
             
                # Returns an <tt>#inspect</tt>-like string for the value of the
         
     | 
| 
         @@ -192,13 +268,13 @@ module ActiveRecord 
     | 
|
| 
       192 
268 
     | 
    
         
             
                # <tt>:db</tt> format. Other attributes return the value of
         
     | 
| 
       193 
269 
     | 
    
         
             
                # <tt>#inspect</tt> without modification.
         
     | 
| 
       194 
270 
     | 
    
         
             
                #
         
     | 
| 
       195 
     | 
    
         
            -
                #   person = Person.create!(: 
     | 
| 
      
 271 
     | 
    
         
            +
                #   person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
         
     | 
| 
       196 
272 
     | 
    
         
             
                #
         
     | 
| 
       197 
273 
     | 
    
         
             
                #   person.attribute_for_inspect(:name)
         
     | 
| 
       198 
     | 
    
         
            -
                #   # =>  
     | 
| 
      
 274 
     | 
    
         
            +
                #   # => "\"David Heinemeier Hansson David Heinemeier Hansson D...\""
         
     | 
| 
       199 
275 
     | 
    
         
             
                #
         
     | 
| 
       200 
276 
     | 
    
         
             
                #   person.attribute_for_inspect(:created_at)
         
     | 
| 
       201 
     | 
    
         
            -
                #   # =>  
     | 
| 
      
 277 
     | 
    
         
            +
                #   # => "\"2012-10-22 00:15:07\""
         
     | 
| 
       202 
278 
     | 
    
         
             
                def attribute_for_inspect(attr_name)
         
     | 
| 
       203 
279 
     | 
    
         
             
                  value = read_attribute(attr_name)
         
     | 
| 
       204 
280 
     | 
    
         | 
| 
         @@ -211,65 +287,149 @@ module ActiveRecord 
     | 
|
| 
       211 
287 
     | 
    
         
             
                  end
         
     | 
| 
       212 
288 
     | 
    
         
             
                end
         
     | 
| 
       213 
289 
     | 
    
         | 
| 
       214 
     | 
    
         
            -
                # Returns true if the specified +attribute+ has been set by the user or by a 
     | 
| 
       215 
     | 
    
         
            -
                # nil nor empty 
     | 
| 
      
 290 
     | 
    
         
            +
                # Returns +true+ if the specified +attribute+ has been set by the user or by a
         
     | 
| 
      
 291 
     | 
    
         
            +
                # database load and is neither +nil+ nor <tt>empty?</tt> (the latter only applies
         
     | 
| 
      
 292 
     | 
    
         
            +
                # to objects that respond to <tt>empty?</tt>, most notably Strings). Otherwise, +false+.
         
     | 
| 
      
 293 
     | 
    
         
            +
                # Note that it always returns +true+ with boolean attributes.
         
     | 
| 
      
 294 
     | 
    
         
            +
                #
         
     | 
| 
      
 295 
     | 
    
         
            +
                #   class Task < ActiveRecord::Base
         
     | 
| 
      
 296 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 297 
     | 
    
         
            +
                #
         
     | 
| 
      
 298 
     | 
    
         
            +
                #   person = Task.new(title: '', is_done: false)
         
     | 
| 
      
 299 
     | 
    
         
            +
                #   person.attribute_present?(:title)   # => false
         
     | 
| 
      
 300 
     | 
    
         
            +
                #   person.attribute_present?(:is_done) # => true
         
     | 
| 
      
 301 
     | 
    
         
            +
                #   person.name = 'Francesco'
         
     | 
| 
      
 302 
     | 
    
         
            +
                #   person.is_done = true
         
     | 
| 
      
 303 
     | 
    
         
            +
                #   person.attribute_present?(:title)   # => true
         
     | 
| 
      
 304 
     | 
    
         
            +
                #   person.attribute_present?(:is_done) # => true
         
     | 
| 
       216 
305 
     | 
    
         
             
                def attribute_present?(attribute)
         
     | 
| 
       217 
306 
     | 
    
         
             
                  value = read_attribute(attribute)
         
     | 
| 
       218 
307 
     | 
    
         
             
                  !value.nil? && !(value.respond_to?(:empty?) && value.empty?)
         
     | 
| 
       219 
308 
     | 
    
         
             
                end
         
     | 
| 
       220 
309 
     | 
    
         | 
| 
       221 
     | 
    
         
            -
                # Returns the column object for the named attribute.
         
     | 
| 
      
 310 
     | 
    
         
            +
                # Returns the column object for the named attribute. Returns +nil+ if the
         
     | 
| 
      
 311 
     | 
    
         
            +
                # named attribute not exists.
         
     | 
| 
      
 312 
     | 
    
         
            +
                #
         
     | 
| 
      
 313 
     | 
    
         
            +
                #   class Person < ActiveRecord::Base
         
     | 
| 
      
 314 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 315 
     | 
    
         
            +
                #
         
     | 
| 
      
 316 
     | 
    
         
            +
                #   person = Person.new
         
     | 
| 
      
 317 
     | 
    
         
            +
                #   person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
         
     | 
| 
      
 318 
     | 
    
         
            +
                #   # => #<ActiveRecord::ConnectionAdapters::SQLite3Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
         
     | 
| 
      
 319 
     | 
    
         
            +
                #
         
     | 
| 
      
 320 
     | 
    
         
            +
                #   person.column_for_attribute(:nothing)
         
     | 
| 
      
 321 
     | 
    
         
            +
                #   # => nil
         
     | 
| 
       222 
322 
     | 
    
         
             
                def column_for_attribute(name)
         
     | 
| 
      
 323 
     | 
    
         
            +
                  # FIXME: should this return a null object for columns that don't exist?
         
     | 
| 
       223 
324 
     | 
    
         
             
                  self.class.columns_hash[name.to_s]
         
     | 
| 
       224 
325 
     | 
    
         
             
                end
         
     | 
| 
       225 
326 
     | 
    
         | 
| 
      
 327 
     | 
    
         
            +
                # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
         
     | 
| 
      
 328 
     | 
    
         
            +
                # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). It raises
         
     | 
| 
      
 329 
     | 
    
         
            +
                # <tt>ActiveModel::MissingAttributeError</tt> if the identified attribute is missing.
         
     | 
| 
      
 330 
     | 
    
         
            +
                #
         
     | 
| 
      
 331 
     | 
    
         
            +
                # Alias for the <tt>read_attribute</tt> method.
         
     | 
| 
      
 332 
     | 
    
         
            +
                #
         
     | 
| 
      
 333 
     | 
    
         
            +
                #   class Person < ActiveRecord::Base
         
     | 
| 
      
 334 
     | 
    
         
            +
                #     belongs_to :organization
         
     | 
| 
      
 335 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 336 
     | 
    
         
            +
                #
         
     | 
| 
      
 337 
     | 
    
         
            +
                #   person = Person.new(name: 'Francesco', age: '22')
         
     | 
| 
      
 338 
     | 
    
         
            +
                #   person[:name] # => "Francesco"
         
     | 
| 
      
 339 
     | 
    
         
            +
                #   person[:age]  # => 22
         
     | 
| 
      
 340 
     | 
    
         
            +
                #
         
     | 
| 
      
 341 
     | 
    
         
            +
                #   person = Person.select('id').first
         
     | 
| 
      
 342 
     | 
    
         
            +
                #   person[:name]            # => ActiveModel::MissingAttributeError: missing attribute: name
         
     | 
| 
      
 343 
     | 
    
         
            +
                #   person[:organization_id] # => ActiveModel::MissingAttributeError: missing attribute: organization_id
         
     | 
| 
      
 344 
     | 
    
         
            +
                def [](attr_name)
         
     | 
| 
      
 345 
     | 
    
         
            +
                  read_attribute(attr_name) { |n| missing_attribute(n, caller) }
         
     | 
| 
      
 346 
     | 
    
         
            +
                end
         
     | 
| 
      
 347 
     | 
    
         
            +
             
     | 
| 
      
 348 
     | 
    
         
            +
                # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
         
     | 
| 
      
 349 
     | 
    
         
            +
                # (Alias for the protected <tt>write_attribute</tt> method).
         
     | 
| 
      
 350 
     | 
    
         
            +
                #
         
     | 
| 
      
 351 
     | 
    
         
            +
                #   class Person < ActiveRecord::Base
         
     | 
| 
      
 352 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 353 
     | 
    
         
            +
                #
         
     | 
| 
      
 354 
     | 
    
         
            +
                #   person = Person.new
         
     | 
| 
      
 355 
     | 
    
         
            +
                #   person[:age] = '22'
         
     | 
| 
      
 356 
     | 
    
         
            +
                #   person[:age] # => 22
         
     | 
| 
      
 357 
     | 
    
         
            +
                #   person[:age] # => Fixnum
         
     | 
| 
      
 358 
     | 
    
         
            +
                def []=(attr_name, value)
         
     | 
| 
      
 359 
     | 
    
         
            +
                  write_attribute(attr_name, value)
         
     | 
| 
      
 360 
     | 
    
         
            +
                end
         
     | 
| 
      
 361 
     | 
    
         
            +
             
     | 
| 
       226 
362 
     | 
    
         
             
                protected
         
     | 
| 
       227 
363 
     | 
    
         | 
| 
       228 
     | 
    
         
            -
                def clone_attributes(reader_method = :read_attribute, attributes = {})
         
     | 
| 
      
 364 
     | 
    
         
            +
                def clone_attributes(reader_method = :read_attribute, attributes = {}) # :nodoc:
         
     | 
| 
       229 
365 
     | 
    
         
             
                  attribute_names.each do |name|
         
     | 
| 
       230 
366 
     | 
    
         
             
                    attributes[name] = clone_attribute_value(reader_method, name)
         
     | 
| 
       231 
367 
     | 
    
         
             
                  end
         
     | 
| 
       232 
368 
     | 
    
         
             
                  attributes
         
     | 
| 
       233 
369 
     | 
    
         
             
                end
         
     | 
| 
       234 
370 
     | 
    
         | 
| 
       235 
     | 
    
         
            -
                def clone_attribute_value(reader_method, attribute_name)
         
     | 
| 
      
 371 
     | 
    
         
            +
                def clone_attribute_value(reader_method, attribute_name) # :nodoc:
         
     | 
| 
       236 
372 
     | 
    
         
             
                  value = send(reader_method, attribute_name)
         
     | 
| 
       237 
373 
     | 
    
         
             
                  value.duplicable? ? value.clone : value
         
     | 
| 
       238 
374 
     | 
    
         
             
                rescue TypeError, NoMethodError
         
     | 
| 
       239 
375 
     | 
    
         
             
                  value
         
     | 
| 
       240 
376 
     | 
    
         
             
                end
         
     | 
| 
       241 
377 
     | 
    
         | 
| 
       242 
     | 
    
         
            -
                 
     | 
| 
       243 
     | 
    
         
            -
             
     | 
| 
       244 
     | 
    
         
            -
                 
     | 
| 
       245 
     | 
    
         
            -
             
     | 
| 
       246 
     | 
    
         
            -
             
     | 
| 
       247 
     | 
    
         
            -
                   
     | 
| 
      
 378 
     | 
    
         
            +
                def arel_attributes_with_values_for_create(attribute_names) # :nodoc:
         
     | 
| 
      
 379 
     | 
    
         
            +
                  arel_attributes_with_values(attributes_for_create(attribute_names))
         
     | 
| 
      
 380 
     | 
    
         
            +
                end
         
     | 
| 
      
 381 
     | 
    
         
            +
             
     | 
| 
      
 382 
     | 
    
         
            +
                def arel_attributes_with_values_for_update(attribute_names) # :nodoc:
         
     | 
| 
      
 383 
     | 
    
         
            +
                  arel_attributes_with_values(attributes_for_update(attribute_names))
         
     | 
| 
      
 384 
     | 
    
         
            +
                end
         
     | 
| 
       248 
385 
     | 
    
         | 
| 
       249 
     | 
    
         
            -
             
     | 
| 
       250 
     | 
    
         
            -
             
     | 
| 
      
 386 
     | 
    
         
            +
                def attribute_method?(attr_name) # :nodoc:
         
     | 
| 
      
 387 
     | 
    
         
            +
                  # We check defined? because Syck calls respond_to? before actually calling initialize.
         
     | 
| 
      
 388 
     | 
    
         
            +
                  defined?(@attributes) && @attributes.include?(attr_name)
         
     | 
| 
      
 389 
     | 
    
         
            +
                end
         
     | 
| 
       251 
390 
     | 
    
         | 
| 
       252 
     | 
    
         
            -
             
     | 
| 
      
 391 
     | 
    
         
            +
                private
         
     | 
| 
       253 
392 
     | 
    
         | 
| 
       254 
     | 
    
         
            -
             
     | 
| 
       255 
     | 
    
         
            -
             
     | 
| 
       256 
     | 
    
         
            -
             
     | 
| 
       257 
     | 
    
         
            -
             
     | 
| 
       258 
     | 
    
         
            -
             
     | 
| 
       259 
     | 
    
         
            -
                                  # casted, this code could be simplified
         
     | 
| 
       260 
     | 
    
         
            -
                                  read_attribute(name)
         
     | 
| 
       261 
     | 
    
         
            -
                                end
         
     | 
| 
      
 393 
     | 
    
         
            +
                # Returns a Hash of the Arel::Attributes and attribute values that have been
         
     | 
| 
      
 394 
     | 
    
         
            +
                # typecasted for use in an Arel insert/update method.
         
     | 
| 
      
 395 
     | 
    
         
            +
                def arel_attributes_with_values(attribute_names)
         
     | 
| 
      
 396 
     | 
    
         
            +
                  attrs = {}
         
     | 
| 
      
 397 
     | 
    
         
            +
                  arel_table = self.class.arel_table
         
     | 
| 
       262 
398 
     | 
    
         | 
| 
       263 
     | 
    
         
            -
             
     | 
| 
       264 
     | 
    
         
            -
             
     | 
| 
       265 
     | 
    
         
            -
                    end
         
     | 
| 
      
 399 
     | 
    
         
            +
                  attribute_names.each do |name|
         
     | 
| 
      
 400 
     | 
    
         
            +
                    attrs[arel_table[name]] = typecasted_attribute_value(name)
         
     | 
| 
       266 
401 
     | 
    
         
             
                  end
         
     | 
| 
       267 
     | 
    
         
            -
             
     | 
| 
       268 
402 
     | 
    
         
             
                  attrs
         
     | 
| 
       269 
403 
     | 
    
         
             
                end
         
     | 
| 
       270 
404 
     | 
    
         | 
| 
       271 
     | 
    
         
            -
                 
     | 
| 
       272 
     | 
    
         
            -
             
     | 
| 
      
 405 
     | 
    
         
            +
                # Filters the primary keys and readonly attributes from the attribute names.
         
     | 
| 
      
 406 
     | 
    
         
            +
                def attributes_for_update(attribute_names)
         
     | 
| 
      
 407 
     | 
    
         
            +
                  attribute_names.select do |name|
         
     | 
| 
      
 408 
     | 
    
         
            +
                    column_for_attribute(name) && !readonly_attribute?(name)
         
     | 
| 
      
 409 
     | 
    
         
            +
                  end
         
     | 
| 
      
 410 
     | 
    
         
            +
                end
         
     | 
| 
      
 411 
     | 
    
         
            +
             
     | 
| 
      
 412 
     | 
    
         
            +
                # Filters out the primary keys, from the attribute names, when the primary
         
     | 
| 
      
 413 
     | 
    
         
            +
                # key is to be generated (e.g. the id attribute has no value).
         
     | 
| 
      
 414 
     | 
    
         
            +
                def attributes_for_create(attribute_names)
         
     | 
| 
      
 415 
     | 
    
         
            +
                  attribute_names.select do |name|
         
     | 
| 
      
 416 
     | 
    
         
            +
                    column_for_attribute(name) && !(pk_attribute?(name) && id.nil?)
         
     | 
| 
      
 417 
     | 
    
         
            +
                  end
         
     | 
| 
      
 418 
     | 
    
         
            +
                end
         
     | 
| 
      
 419 
     | 
    
         
            +
             
     | 
| 
      
 420 
     | 
    
         
            +
                def readonly_attribute?(name)
         
     | 
| 
      
 421 
     | 
    
         
            +
                  self.class.readonly_attributes.include?(name)
         
     | 
| 
      
 422 
     | 
    
         
            +
                end
         
     | 
| 
      
 423 
     | 
    
         
            +
             
     | 
| 
      
 424 
     | 
    
         
            +
                def pk_attribute?(name)
         
     | 
| 
      
 425 
     | 
    
         
            +
                  column_for_attribute(name).primary
         
     | 
| 
      
 426 
     | 
    
         
            +
                end
         
     | 
| 
      
 427 
     | 
    
         
            +
             
     | 
| 
      
 428 
     | 
    
         
            +
                def typecasted_attribute_value(name)
         
     | 
| 
      
 429 
     | 
    
         
            +
                  # FIXME: we need @attributes to be used consistently.
         
     | 
| 
      
 430 
     | 
    
         
            +
                  # If the values stored in @attributes were already typecasted, this code
         
     | 
| 
      
 431 
     | 
    
         
            +
                  # could be simplified
         
     | 
| 
      
 432 
     | 
    
         
            +
                  read_attribute(name)
         
     | 
| 
       273 
433 
     | 
    
         
             
                end
         
     | 
| 
       274 
434 
     | 
    
         
             
              end
         
     | 
| 
       275 
435 
     | 
    
         
             
            end
         
     |