activerecord 3.2.22.5 → 5.2.8
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +657 -621
- data/MIT-LICENSE +2 -2
- data/README.rdoc +41 -46
- data/examples/performance.rb +55 -42
- data/examples/simple.rb +6 -5
- data/lib/active_record/aggregations.rb +264 -236
- data/lib/active_record/association_relation.rb +40 -0
- data/lib/active_record/associations/alias_tracker.rb +47 -42
- data/lib/active_record/associations/association.rb +127 -75
- data/lib/active_record/associations/association_scope.rb +126 -92
- data/lib/active_record/associations/belongs_to_association.rb +78 -27
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +9 -4
- data/lib/active_record/associations/builder/association.rb +117 -32
- data/lib/active_record/associations/builder/belongs_to.rb +135 -60
- data/lib/active_record/associations/builder/collection_association.rb +61 -54
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +120 -42
- data/lib/active_record/associations/builder/has_many.rb +10 -64
- data/lib/active_record/associations/builder/has_one.rb +19 -51
- data/lib/active_record/associations/builder/singular_association.rb +28 -18
- data/lib/active_record/associations/collection_association.rb +226 -293
- data/lib/active_record/associations/collection_proxy.rb +1067 -69
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +83 -47
- data/lib/active_record/associations/has_many_through_association.rb +98 -65
- data/lib/active_record/associations/has_one_association.rb +57 -20
- data/lib/active_record/associations/has_one_through_association.rb +18 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +48 -126
- data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
- data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
- data/lib/active_record/associations/join_dependency.rb +212 -164
- data/lib/active_record/associations/preloader/association.rb +95 -89
- data/lib/active_record/associations/preloader/through_association.rb +84 -44
- data/lib/active_record/associations/preloader.rb +123 -111
- data/lib/active_record/associations/singular_association.rb +33 -24
- data/lib/active_record/associations/through_association.rb +60 -26
- data/lib/active_record/associations.rb +1759 -1506
- data/lib/active_record/attribute_assignment.rb +60 -193
- data/lib/active_record/attribute_decorators.rb +90 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +55 -8
- data/lib/active_record/attribute_methods/dirty.rb +113 -74
- data/lib/active_record/attribute_methods/primary_key.rb +106 -77
- data/lib/active_record/attribute_methods/query.rb +8 -5
- data/lib/active_record/attribute_methods/read.rb +63 -114
- data/lib/active_record/attribute_methods/serialization.rb +60 -90
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -43
- data/lib/active_record/attribute_methods/write.rb +43 -45
- data/lib/active_record/attribute_methods.rb +366 -149
- data/lib/active_record/attributes.rb +266 -0
- data/lib/active_record/autosave_association.rb +312 -225
- data/lib/active_record/base.rb +114 -505
- data/lib/active_record/callbacks.rb +145 -67
- data/lib/active_record/coders/json.rb +15 -0
- data/lib/active_record/coders/yaml_column.rb +32 -23
- data/lib/active_record/collection_cache_key.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +883 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +16 -2
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +350 -200
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +150 -65
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +146 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +477 -284
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +95 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1100 -310
- data/lib/active_record/connection_adapters/abstract/transaction.rb +283 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +450 -118
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +657 -446
- data/lib/active_record/connection_adapters/column.rb +50 -255
- data/lib/active_record/connection_adapters/connection_specification.rb +287 -0
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -210
- data/lib/active_record/connection_adapters/postgresql/column.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +163 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +56 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +111 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +168 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +206 -0
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +774 -0
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +620 -1080
- data/lib/active_record/connection_adapters/schema_cache.rb +85 -36
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +545 -27
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +145 -0
- data/lib/active_record/core.rb +559 -0
- data/lib/active_record/counter_cache.rb +200 -105
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +107 -69
- data/lib/active_record/enum.rb +244 -0
- data/lib/active_record/errors.rb +245 -60
- data/lib/active_record/explain.rb +35 -71
- data/lib/active_record/explain_registry.rb +32 -0
- data/lib/active_record/explain_subscriber.rb +18 -9
- data/lib/active_record/fixture_set/file.rb +82 -0
- data/lib/active_record/fixtures.rb +418 -275
- data/lib/active_record/gem_version.rb +17 -0
- data/lib/active_record/inheritance.rb +209 -100
- data/lib/active_record/integration.rb +116 -21
- data/lib/active_record/internal_metadata.rb +45 -0
- data/lib/active_record/legacy_yaml_adapter.rb +48 -0
- data/lib/active_record/locale/en.yml +9 -1
- data/lib/active_record/locking/optimistic.rb +107 -94
- data/lib/active_record/locking/pessimistic.rb +20 -8
- data/lib/active_record/log_subscriber.rb +99 -34
- data/lib/active_record/migration/command_recorder.rb +199 -64
- data/lib/active_record/migration/compatibility.rb +217 -0
- data/lib/active_record/migration/join_table.rb +17 -0
- data/lib/active_record/migration.rb +893 -296
- data/lib/active_record/model_schema.rb +328 -175
- data/lib/active_record/nested_attributes.rb +338 -242
- data/lib/active_record/no_touching.rb +58 -0
- data/lib/active_record/null_relation.rb +68 -0
- data/lib/active_record/persistence.rb +557 -170
- data/lib/active_record/query_cache.rb +14 -43
- data/lib/active_record/querying.rb +36 -24
- data/lib/active_record/railtie.rb +147 -52
- data/lib/active_record/railties/console_sandbox.rb +5 -4
- data/lib/active_record/railties/controller_runtime.rb +13 -6
- data/lib/active_record/railties/databases.rake +206 -488
- data/lib/active_record/readonly_attributes.rb +4 -6
- data/lib/active_record/reflection.rb +734 -228
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +249 -52
- data/lib/active_record/relation/calculations.rb +330 -284
- data/lib/active_record/relation/delegation.rb +135 -37
- data/lib/active_record/relation/finder_methods.rb +450 -287
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +193 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder.rb +132 -43
- data/lib/active_record/relation/query_attribute.rb +45 -0
- data/lib/active_record/relation/query_methods.rb +1037 -221
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +48 -151
- data/lib/active_record/relation/where_clause.rb +186 -0
- data/lib/active_record/relation/where_clause_factory.rb +34 -0
- data/lib/active_record/relation.rb +451 -359
- data/lib/active_record/result.rb +129 -20
- data/lib/active_record/runtime_registry.rb +24 -0
- data/lib/active_record/sanitization.rb +164 -136
- data/lib/active_record/schema.rb +31 -19
- data/lib/active_record/schema_dumper.rb +154 -107
- data/lib/active_record/schema_migration.rb +56 -0
- data/lib/active_record/scoping/default.rb +108 -98
- data/lib/active_record/scoping/named.rb +125 -112
- data/lib/active_record/scoping.rb +77 -123
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +10 -6
- data/lib/active_record/statement_cache.rb +121 -0
- data/lib/active_record/store.rb +175 -16
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +82 -0
- data/lib/active_record/tasks/database_tasks.rb +337 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +143 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +83 -0
- data/lib/active_record/timestamp.rb +80 -41
- data/lib/active_record/touch_later.rb +64 -0
- data/lib/active_record/transactions.rb +240 -119
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type/adapter_specific_registry.rb +136 -0
- data/lib/active_record/type/date.rb +9 -0
- data/lib/active_record/type/date_time.rb +9 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +71 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +21 -0
- data/lib/active_record/type/type_map.rb +62 -0
- data/lib/active_record/type/unsigned_integer.rb +17 -0
- data/lib/active_record/type.rb +79 -0
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +35 -18
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +68 -0
- data/lib/active_record/validations/uniqueness.rb +133 -75
- data/lib/active_record/validations.rb +53 -43
- data/lib/active_record/version.rb +7 -7
- data/lib/active_record.rb +89 -57
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +61 -8
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +46 -0
- data/lib/rails/generators/active_record/migration.rb +28 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +23 -22
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +13 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +1 -1
- data/lib/rails/generators/active_record.rb +10 -16
- metadata +141 -62
- data/examples/associations.png +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
- data/lib/active_record/associations/join_helper.rb +0 -55
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- 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/mysql_adapter.rb +0 -441
- 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/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -203
- data/lib/active_record/session_store.rb +0 -360
- data/lib/active_record/test_case.rb +0 -73
- data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
- 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/lib/active_record/base.rb
CHANGED
@@ -1,34 +1,28 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
23
|
-
require
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require 'active_support/core_ext/object/blank'
|
27
|
-
require 'active_support/deprecation'
|
28
|
-
require 'arel'
|
29
|
-
require 'active_record/errors'
|
30
|
-
require 'active_record/log_subscriber'
|
31
|
-
require 'active_record/explain_subscriber'
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require "active_support/benchmarkable"
|
5
|
+
require "active_support/dependencies"
|
6
|
+
require "active_support/descendants_tracker"
|
7
|
+
require "active_support/time"
|
8
|
+
require "active_support/core_ext/module/attribute_accessors"
|
9
|
+
require "active_support/core_ext/array/extract_options"
|
10
|
+
require "active_support/core_ext/hash/deep_merge"
|
11
|
+
require "active_support/core_ext/hash/slice"
|
12
|
+
require "active_support/core_ext/hash/transform_values"
|
13
|
+
require "active_support/core_ext/string/behavior"
|
14
|
+
require "active_support/core_ext/kernel/singleton_class"
|
15
|
+
require "active_support/core_ext/module/introspection"
|
16
|
+
require "active_support/core_ext/object/duplicable"
|
17
|
+
require "active_support/core_ext/class/subclasses"
|
18
|
+
require "active_record/attribute_decorators"
|
19
|
+
require "active_record/define_callbacks"
|
20
|
+
require "active_record/errors"
|
21
|
+
require "active_record/log_subscriber"
|
22
|
+
require "active_record/explain_subscriber"
|
23
|
+
require "active_record/relation/delegation"
|
24
|
+
require "active_record/attributes"
|
25
|
+
require "active_record/type_caster"
|
32
26
|
|
33
27
|
module ActiveRecord #:nodoc:
|
34
28
|
# = Active Record
|
@@ -47,7 +41,7 @@ module ActiveRecord #:nodoc:
|
|
47
41
|
# method is especially useful when you're receiving the data from somewhere else, like an
|
48
42
|
# HTTP request. It works like this:
|
49
43
|
#
|
50
|
-
# user = User.new(:
|
44
|
+
# user = User.new(name: "David", occupation: "Code Artist")
|
51
45
|
# user.name # => "David"
|
52
46
|
#
|
53
47
|
# You can also use block initialization:
|
@@ -80,7 +74,7 @@ module ActiveRecord #:nodoc:
|
|
80
74
|
# end
|
81
75
|
#
|
82
76
|
# def self.authenticate_safely_simply(user_name, password)
|
83
|
-
# where(:
|
77
|
+
# where(user_name: user_name, password: password).first
|
84
78
|
# end
|
85
79
|
# end
|
86
80
|
#
|
@@ -98,27 +92,27 @@ module ActiveRecord #:nodoc:
|
|
98
92
|
#
|
99
93
|
# Company.where(
|
100
94
|
# "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
|
101
|
-
# { :
|
95
|
+
# { id: 3, name: "37signals", division: "First", accounting_date: '2005-01-01' }
|
102
96
|
# ).first
|
103
97
|
#
|
104
98
|
# Similarly, a simple hash without a statement will generate conditions based on equality with the SQL AND
|
105
99
|
# operator. For instance:
|
106
100
|
#
|
107
|
-
# Student.where(:
|
101
|
+
# Student.where(first_name: "Harvey", status: 1)
|
108
102
|
# Student.where(params[:student])
|
109
103
|
#
|
110
104
|
# A range may be used in the hash to use the SQL BETWEEN operator:
|
111
105
|
#
|
112
|
-
# Student.where(:
|
106
|
+
# Student.where(grade: 9..12)
|
113
107
|
#
|
114
108
|
# An array may be used in the hash to use the SQL IN operator:
|
115
109
|
#
|
116
|
-
# Student.where(:
|
110
|
+
# Student.where(grade: [9,11,12])
|
117
111
|
#
|
118
112
|
# When joining tables, nested hashes or keys written in the form 'table_name.column_name'
|
119
113
|
# can be used to qualify the table name of a particular condition. For instance:
|
120
114
|
#
|
121
|
-
# Student.joins(:schools).where(:
|
115
|
+
# Student.joins(:schools).where(schools: { category: 'public' })
|
122
116
|
# Student.joins(:schools).where('schools.category' => 'public' )
|
123
117
|
#
|
124
118
|
# == Overwriting default accessors
|
@@ -126,36 +120,33 @@ module ActiveRecord #:nodoc:
|
|
126
120
|
# All column values are automatically available through basic accessors on the Active Record
|
127
121
|
# object, but sometimes you want to specialize this behavior. This can be done by overwriting
|
128
122
|
# the default accessors (using the same name as the attribute) and calling
|
129
|
-
#
|
130
|
-
# change things.
|
123
|
+
# +super+ to actually change things.
|
131
124
|
#
|
132
125
|
# class Song < ActiveRecord::Base
|
133
126
|
# # Uses an integer of seconds to hold the length of the song
|
134
127
|
#
|
135
128
|
# def length=(minutes)
|
136
|
-
#
|
129
|
+
# super(minutes.to_i * 60)
|
137
130
|
# end
|
138
131
|
#
|
139
132
|
# def length
|
140
|
-
#
|
133
|
+
# super / 60
|
141
134
|
# end
|
142
135
|
# end
|
143
136
|
#
|
144
|
-
# You can alternatively use <tt>self[:attribute]=(value)</tt> and <tt>self[:attribute]</tt>
|
145
|
-
# instead of <tt>write_attribute(:attribute, value)</tt> and <tt>read_attribute(:attribute)</tt>.
|
146
|
-
#
|
147
137
|
# == Attribute query methods
|
148
138
|
#
|
149
139
|
# In addition to the basic accessors, query methods are also automatically available on the Active Record object.
|
150
140
|
# Query methods allow you to test whether an attribute value is present.
|
141
|
+
# Additionally, when dealing with numeric values, a query method will return false if the value is zero.
|
151
142
|
#
|
152
143
|
# For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
|
153
144
|
# to determine whether the user has a name:
|
154
145
|
#
|
155
|
-
# user = User.new(:
|
146
|
+
# user = User.new(name: "David")
|
156
147
|
# user.name? # => true
|
157
148
|
#
|
158
|
-
# anonymous = User.new(:
|
149
|
+
# anonymous = User.new(name: "")
|
159
150
|
# anonymous.name? # => false
|
160
151
|
#
|
161
152
|
# == Accessing attributes before they have been typecasted
|
@@ -171,71 +162,31 @@ module ActiveRecord #:nodoc:
|
|
171
162
|
#
|
172
163
|
# == Dynamic attribute-based finders
|
173
164
|
#
|
174
|
-
# Dynamic attribute-based finders are a
|
165
|
+
# Dynamic attribute-based finders are a mildly deprecated way of getting (and/or creating) objects
|
175
166
|
# by simple queries without turning to SQL. They work by appending the name of an attribute
|
176
|
-
# to <tt>find_by_</tt
|
177
|
-
#
|
178
|
-
# <tt>
|
179
|
-
# <tt>Person.where(:user_name => user_name).first</tt>, you just do <tt>Person.find_by_user_name(user_name)</tt>.
|
180
|
-
# And instead of writing <tt>Person.where(:last_name => last_name).all</tt>, you just do
|
181
|
-
# <tt>Person.find_all_by_last_name(last_name)</tt>.
|
167
|
+
# to <tt>find_by_</tt> like <tt>Person.find_by_user_name</tt>.
|
168
|
+
# Instead of writing <tt>Person.find_by(user_name: user_name)</tt>, you can use
|
169
|
+
# <tt>Person.find_by_user_name(user_name)</tt>.
|
182
170
|
#
|
183
171
|
# It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
|
184
|
-
#
|
172
|
+
# ActiveRecord::RecordNotFound error if they do not return any records,
|
185
173
|
# like <tt>Person.find_by_last_name!</tt>.
|
186
174
|
#
|
187
|
-
# It's also possible to use multiple attributes in the same
|
175
|
+
# It's also possible to use multiple attributes in the same <tt>find_by_</tt> by separating them with
|
176
|
+
# "_and_".
|
188
177
|
#
|
189
|
-
# Person.
|
178
|
+
# Person.find_by(user_name: user_name, password: password)
|
190
179
|
# Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
|
191
180
|
#
|
192
181
|
# It's even possible to call these dynamic finder methods on relations and named scopes.
|
193
182
|
#
|
194
|
-
# Payment.order("created_on").
|
195
|
-
# Payment.pending.find_last_by_amount(100)
|
196
|
-
#
|
197
|
-
# The same dynamic finder style can be used to create the object if it doesn't already exist.
|
198
|
-
# This dynamic finder is called with <tt>find_or_create_by_</tt> and will return the object if
|
199
|
-
# it already exists and otherwise creates it, then returns it. Protected attributes won't be set
|
200
|
-
# unless they are given in a block.
|
201
|
-
#
|
202
|
-
# # No 'Summer' tag exists
|
203
|
-
# Tag.find_or_create_by_name("Summer") # equal to Tag.create(:name => "Summer")
|
204
|
-
#
|
205
|
-
# # Now the 'Summer' tag does exist
|
206
|
-
# Tag.find_or_create_by_name("Summer") # equal to Tag.find_by_name("Summer")
|
207
|
-
#
|
208
|
-
# # Now 'Bob' exist and is an 'admin'
|
209
|
-
# User.find_or_create_by_name('Bob', :age => 40) { |u| u.admin = true }
|
210
|
-
#
|
211
|
-
# Adding an exclamation point (!) on to the end of <tt>find_or_create_by_</tt> will
|
212
|
-
# raise an <tt>ActiveRecord::RecordInvalid</tt> error if the new record is invalid.
|
213
|
-
#
|
214
|
-
# Use the <tt>find_or_initialize_by_</tt> finder if you want to return a new record without
|
215
|
-
# saving it first. Protected attributes won't be set unless they are given in a block.
|
216
|
-
#
|
217
|
-
# # No 'Winter' tag exists
|
218
|
-
# winter = Tag.find_or_initialize_by_name("Winter")
|
219
|
-
# winter.persisted? # false
|
220
|
-
#
|
221
|
-
# To find by a subset of the attributes to be used for instantiating a new object, pass a hash instead of
|
222
|
-
# a list of parameters.
|
223
|
-
#
|
224
|
-
# Tag.find_or_create_by_name(:name => "rails", :creator => current_user)
|
225
|
-
#
|
226
|
-
# That will either find an existing tag named "rails", or create a new one while setting the
|
227
|
-
# user that created it.
|
228
|
-
#
|
229
|
-
# Just like <tt>find_by_*</tt>, you can also use <tt>scoped_by_*</tt> to retrieve data. The good thing about
|
230
|
-
# using this feature is that the very first time result is returned using <tt>method_missing</tt> technique
|
231
|
-
# but after that the method is declared on the class. Henceforth <tt>method_missing</tt> will not be hit.
|
232
|
-
#
|
233
|
-
# User.scoped_by_user_name('David')
|
183
|
+
# Payment.order("created_on").find_by_amount(50)
|
234
184
|
#
|
235
185
|
# == Saving arrays, hashes, and other non-mappable objects in text columns
|
236
186
|
#
|
237
187
|
# Active Record can serialize any object in text columns using YAML. To do so, you must
|
238
|
-
# specify this with a call to the class method
|
188
|
+
# specify this with a call to the class method
|
189
|
+
# {serialize}[rdoc-ref:AttributeMethods::Serialization::ClassMethods#serialize].
|
239
190
|
# This makes it possible to store arrays, hashes, and other non-mappable objects without doing
|
240
191
|
# any additional work.
|
241
192
|
#
|
@@ -243,7 +194,7 @@ module ActiveRecord #:nodoc:
|
|
243
194
|
# serialize :preferences
|
244
195
|
# end
|
245
196
|
#
|
246
|
-
# user = User.create(:
|
197
|
+
# user = User.create(preferences: { "background" => "black", "display" => large })
|
247
198
|
# User.find(user.id).preferences # => { "background" => "black", "display" => large }
|
248
199
|
#
|
249
200
|
# You can also specify a class option as the second parameter that'll raise an exception
|
@@ -253,7 +204,7 @@ module ActiveRecord #:nodoc:
|
|
253
204
|
# serialize :preferences, Hash
|
254
205
|
# end
|
255
206
|
#
|
256
|
-
# user = User.create(:
|
207
|
+
# user = User.create(preferences: %w( one two three ))
|
257
208
|
# User.find(user.id).preferences # raises SerializationTypeMismatch
|
258
209
|
#
|
259
210
|
# When you specify a class option, the default value for that attribute will be a new
|
@@ -269,452 +220,110 @@ module ActiveRecord #:nodoc:
|
|
269
220
|
#
|
270
221
|
# == Single table inheritance
|
271
222
|
#
|
272
|
-
# Active Record allows inheritance by storing the name of the class in a
|
273
|
-
#
|
274
|
-
#
|
275
|
-
#
|
276
|
-
# class Company < ActiveRecord::Base; end
|
277
|
-
# class Firm < Company; end
|
278
|
-
# class Client < Company; end
|
279
|
-
# class PriorityClient < Client; end
|
280
|
-
#
|
281
|
-
# When you do <tt>Firm.create(:name => "37signals")</tt>, this record will be saved in
|
282
|
-
# the companies table with type = "Firm". You can then fetch this row again using
|
283
|
-
# <tt>Company.where(:name => '37signals').first</tt> and it will return a Firm object.
|
284
|
-
#
|
285
|
-
# If you don't have a type column defined in your table, single-table inheritance won't
|
286
|
-
# be triggered. In that case, it'll work just like normal subclasses with no special magic
|
287
|
-
# for differentiating between them or reloading the right type with find.
|
288
|
-
#
|
289
|
-
# Note, all the attributes for all the cases are kept in the same table. Read more:
|
290
|
-
# http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
|
223
|
+
# Active Record allows inheritance by storing the name of the class in a
|
224
|
+
# column that is named "type" by default. See ActiveRecord::Inheritance for
|
225
|
+
# more details.
|
291
226
|
#
|
292
227
|
# == Connection to multiple databases in different models
|
293
228
|
#
|
294
|
-
# Connections are usually created through
|
229
|
+
# Connections are usually created through
|
230
|
+
# {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] and retrieved
|
295
231
|
# by ActiveRecord::Base.connection. All classes inheriting from ActiveRecord::Base will use this
|
296
232
|
# connection. But you can also set a class-specific connection. For example, if Course is an
|
297
233
|
# ActiveRecord::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
|
298
234
|
# and Course and all of its subclasses will use this connection instead.
|
299
235
|
#
|
300
236
|
# This feature is implemented by keeping a connection pool in ActiveRecord::Base that is
|
301
|
-
# a
|
237
|
+
# a hash indexed by the class. If a connection is requested, the
|
238
|
+
# {ActiveRecord::Base.retrieve_connection}[rdoc-ref:ConnectionHandling#retrieve_connection] method
|
302
239
|
# will go up the class-hierarchy until a connection is found in the connection pool.
|
303
240
|
#
|
304
241
|
# == Exceptions
|
305
242
|
#
|
306
243
|
# * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
|
307
|
-
# * AdapterNotSpecified - The configuration hash used in
|
308
|
-
#
|
309
|
-
#
|
310
|
-
#
|
244
|
+
# * AdapterNotSpecified - The configuration hash used in
|
245
|
+
# {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
|
246
|
+
# didn't include an <tt>:adapter</tt> key.
|
247
|
+
# * AdapterNotFound - The <tt>:adapter</tt> key used in
|
248
|
+
# {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
|
249
|
+
# specified a non-existent adapter
|
311
250
|
# (or a bad spelling of an existing one).
|
312
251
|
# * AssociationTypeMismatch - The object assigned to the association wasn't of the type
|
313
252
|
# specified in the association definition.
|
314
|
-
# * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
|
315
|
-
# * ConnectionNotEstablished+ - No connection has been established. Use <tt>establish_connection</tt>
|
316
|
-
# before querying.
|
317
|
-
# * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
|
318
|
-
# or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
|
319
|
-
# nothing was found, please check its documentation for further details.
|
320
|
-
# * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
|
321
|
-
# * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
|
322
|
-
# <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of
|
323
|
-
# AttributeAssignmentError
|
324
|
-
# objects that should be inspected to determine which attributes triggered the errors.
|
325
253
|
# * AttributeAssignmentError - An error occurred while doing a mass assignment through the
|
326
|
-
#
|
254
|
+
# {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
|
327
255
|
# You can inspect the +attribute+ property of the exception object to determine which attribute
|
328
256
|
# triggered the error.
|
257
|
+
# * ConnectionNotEstablished - No connection has been established.
|
258
|
+
# Use {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] before querying.
|
259
|
+
# * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
|
260
|
+
# {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
|
261
|
+
# The +errors+ property of this exception contains an array of
|
262
|
+
# AttributeAssignmentError
|
263
|
+
# objects that should be inspected to determine which attributes triggered the errors.
|
264
|
+
# * RecordInvalid - raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
|
265
|
+
# {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
|
266
|
+
# when the record is invalid.
|
267
|
+
# * RecordNotFound - No record responded to the {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method.
|
268
|
+
# Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions.
|
269
|
+
# Some {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] calls do not raise this exception to signal
|
270
|
+
# nothing was found, please check its documentation for further details.
|
271
|
+
# * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
|
272
|
+
# * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
|
329
273
|
#
|
330
274
|
# *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level).
|
331
275
|
# So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all
|
332
276
|
# instances in the current object space.
|
333
277
|
class Base
|
334
|
-
##
|
335
|
-
# :singleton-method:
|
336
|
-
# Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class,
|
337
|
-
# which is then passed on to any new database connections made and which can be retrieved on both
|
338
|
-
# a class and instance level by calling +logger+.
|
339
|
-
cattr_accessor :logger, :instance_writer => false
|
340
|
-
|
341
|
-
##
|
342
|
-
# :singleton-method:
|
343
|
-
# Contains the database configuration - as is typically stored in config/database.yml -
|
344
|
-
# as a Hash.
|
345
|
-
#
|
346
|
-
# For example, the following database.yml...
|
347
|
-
#
|
348
|
-
# development:
|
349
|
-
# adapter: sqlite3
|
350
|
-
# database: db/development.sqlite3
|
351
|
-
#
|
352
|
-
# production:
|
353
|
-
# adapter: sqlite3
|
354
|
-
# database: db/production.sqlite3
|
355
|
-
#
|
356
|
-
# ...would result in ActiveRecord::Base.configurations to look like this:
|
357
|
-
#
|
358
|
-
# {
|
359
|
-
# 'development' => {
|
360
|
-
# 'adapter' => 'sqlite3',
|
361
|
-
# 'database' => 'db/development.sqlite3'
|
362
|
-
# },
|
363
|
-
# 'production' => {
|
364
|
-
# 'adapter' => 'sqlite3',
|
365
|
-
# 'database' => 'db/production.sqlite3'
|
366
|
-
# }
|
367
|
-
# }
|
368
|
-
cattr_accessor :configurations, :instance_writer => false
|
369
|
-
@@configurations = {}
|
370
|
-
|
371
|
-
##
|
372
|
-
# :singleton-method:
|
373
|
-
# Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling
|
374
|
-
# dates and times from the database. This is set to :local by default.
|
375
|
-
cattr_accessor :default_timezone, :instance_writer => false
|
376
|
-
@@default_timezone = :local
|
377
|
-
|
378
|
-
##
|
379
|
-
# :singleton-method:
|
380
|
-
# Specifies the format to use when dumping the database schema with Rails'
|
381
|
-
# Rakefile. If :sql, the schema is dumped as (potentially database-
|
382
|
-
# specific) SQL statements. If :ruby, the schema is dumped as an
|
383
|
-
# ActiveRecord::Schema file which can be loaded into any database that
|
384
|
-
# supports migrations. Use :ruby if you want to have different database
|
385
|
-
# adapters for, e.g., your development and test environments.
|
386
|
-
cattr_accessor :schema_format , :instance_writer => false
|
387
|
-
@@schema_format = :ruby
|
388
|
-
|
389
|
-
##
|
390
|
-
# :singleton-method:
|
391
|
-
# Specify whether or not to use timestamps for migration versions
|
392
|
-
cattr_accessor :timestamped_migrations , :instance_writer => false
|
393
|
-
@@timestamped_migrations = true
|
394
|
-
|
395
|
-
class << self # Class methods
|
396
|
-
def inherited(child_class) #:nodoc:
|
397
|
-
child_class.initialize_generated_modules
|
398
|
-
super
|
399
|
-
end
|
400
|
-
|
401
|
-
def initialize_generated_modules #:nodoc:
|
402
|
-
@attribute_methods_mutex = Mutex.new
|
403
|
-
|
404
|
-
# force attribute methods to be higher in inheritance hierarchy than other generated methods
|
405
|
-
generated_attribute_methods
|
406
|
-
generated_feature_methods
|
407
|
-
end
|
408
|
-
|
409
|
-
def generated_feature_methods
|
410
|
-
@generated_feature_methods ||= begin
|
411
|
-
mod = const_set(:GeneratedFeatureMethods, Module.new)
|
412
|
-
include mod
|
413
|
-
mod
|
414
|
-
end
|
415
|
-
end
|
416
|
-
|
417
|
-
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
418
|
-
def inspect
|
419
|
-
if self == Base
|
420
|
-
super
|
421
|
-
elsif abstract_class?
|
422
|
-
"#{super}(abstract)"
|
423
|
-
elsif table_exists?
|
424
|
-
attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
|
425
|
-
"#{super}(#{attr_list})"
|
426
|
-
else
|
427
|
-
"#{super}(Table doesn't exist)"
|
428
|
-
end
|
429
|
-
end
|
430
|
-
|
431
|
-
# Overwrite the default class equality method to provide support for association proxies.
|
432
|
-
def ===(object)
|
433
|
-
object.is_a?(self)
|
434
|
-
end
|
435
|
-
|
436
|
-
def arel_table
|
437
|
-
@arel_table ||= Arel::Table.new(table_name, arel_engine)
|
438
|
-
end
|
439
|
-
|
440
|
-
def arel_engine
|
441
|
-
@arel_engine ||= begin
|
442
|
-
if self == ActiveRecord::Base
|
443
|
-
ActiveRecord::Base
|
444
|
-
else
|
445
|
-
connection_handler.retrieve_connection_pool(self) ? self : superclass.arel_engine
|
446
|
-
end
|
447
|
-
end
|
448
|
-
end
|
449
|
-
|
450
|
-
private
|
451
|
-
|
452
|
-
def relation #:nodoc:
|
453
|
-
relation = Relation.new(self, arel_table)
|
454
|
-
|
455
|
-
if finder_needs_type_condition?
|
456
|
-
relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
|
457
|
-
else
|
458
|
-
relation
|
459
|
-
end
|
460
|
-
end
|
461
|
-
end
|
462
|
-
|
463
|
-
public
|
464
|
-
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
465
|
-
# attributes but not yet saved (pass a hash with key names matching the associated table column names).
|
466
|
-
# In both instances, valid attribute keys are determined by the column names of the associated table --
|
467
|
-
# hence you can't have attributes that aren't part of the table columns.
|
468
|
-
#
|
469
|
-
# +initialize+ respects mass-assignment security and accepts either +:as+ or +:without_protection+ options
|
470
|
-
# in the +options+ parameter.
|
471
|
-
#
|
472
|
-
# ==== Examples
|
473
|
-
# # Instantiates a single new object
|
474
|
-
# User.new(:first_name => 'Jamie')
|
475
|
-
#
|
476
|
-
# # Instantiates a single new object using the :admin mass-assignment security role
|
477
|
-
# User.new({ :first_name => 'Jamie', :is_admin => true }, :as => :admin)
|
478
|
-
#
|
479
|
-
# # Instantiates a single new object bypassing mass-assignment security
|
480
|
-
# User.new({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true)
|
481
|
-
def initialize(attributes = nil, options = {})
|
482
|
-
defaults = Hash[self.class.column_defaults.map { |k, v| [k, v.duplicable? ? v.dup : v] }]
|
483
|
-
@attributes = self.class.initialize_attributes(defaults)
|
484
|
-
@association_cache = {}
|
485
|
-
@aggregation_cache = {}
|
486
|
-
@attributes_cache = {}
|
487
|
-
@new_record = true
|
488
|
-
@readonly = false
|
489
|
-
@destroyed = false
|
490
|
-
@marked_for_destruction = false
|
491
|
-
@previously_changed = {}
|
492
|
-
@changed_attributes = {}
|
493
|
-
|
494
|
-
ensure_proper_type
|
495
|
-
|
496
|
-
populate_with_current_scope_attributes
|
497
|
-
|
498
|
-
assign_attributes(attributes, options) if attributes
|
499
|
-
|
500
|
-
yield self if block_given?
|
501
|
-
run_callbacks :initialize
|
502
|
-
end
|
503
|
-
|
504
|
-
# Initialize an empty model object from +coder+. +coder+ must contain
|
505
|
-
# the attributes necessary for initializing an empty model object. For
|
506
|
-
# example:
|
507
|
-
#
|
508
|
-
# class Post < ActiveRecord::Base
|
509
|
-
# end
|
510
|
-
#
|
511
|
-
# post = Post.allocate
|
512
|
-
# post.init_with('attributes' => { 'title' => 'hello world' })
|
513
|
-
# post.title # => 'hello world'
|
514
|
-
def init_with(coder)
|
515
|
-
@attributes = self.class.initialize_attributes(coder['attributes'])
|
516
|
-
@relation = nil
|
517
|
-
|
518
|
-
@attributes_cache, @previously_changed, @changed_attributes = {}, {}, {}
|
519
|
-
@association_cache = {}
|
520
|
-
@aggregation_cache = {}
|
521
|
-
@readonly = @destroyed = @marked_for_destruction = false
|
522
|
-
@new_record = false
|
523
|
-
run_callbacks :find
|
524
|
-
run_callbacks :initialize
|
525
|
-
|
526
|
-
self
|
527
|
-
end
|
528
|
-
|
529
|
-
# Duped objects have no id assigned and are treated as new records. Note
|
530
|
-
# that this is a "shallow" copy as it copies the object's attributes
|
531
|
-
# only, not its associations. The extent of a "deep" copy is application
|
532
|
-
# specific and is therefore left to the application to implement according
|
533
|
-
# to its need.
|
534
|
-
# The dup method does not preserve the timestamps (created|updated)_(at|on).
|
535
|
-
def initialize_dup(other)
|
536
|
-
cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
|
537
|
-
self.class.initialize_attributes(cloned_attributes, :serialized => false)
|
538
|
-
|
539
|
-
cloned_attributes.delete(self.class.primary_key)
|
540
|
-
|
541
|
-
@attributes = cloned_attributes
|
542
|
-
|
543
|
-
_run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks)
|
544
|
-
|
545
|
-
@changed_attributes = {}
|
546
|
-
self.class.column_defaults.each do |attr, orig_value|
|
547
|
-
@changed_attributes[attr] = orig_value if _field_changed?(attr, orig_value, @attributes[attr])
|
548
|
-
end
|
549
|
-
|
550
|
-
@aggregation_cache = {}
|
551
|
-
@association_cache = {}
|
552
|
-
@attributes_cache = {}
|
553
|
-
@new_record = true
|
554
|
-
|
555
|
-
ensure_proper_type
|
556
|
-
super
|
557
|
-
end
|
558
|
-
|
559
|
-
# Backport dup from 1.9 so that initialize_dup() gets called
|
560
|
-
unless Object.respond_to?(:initialize_dup, true)
|
561
|
-
def dup # :nodoc:
|
562
|
-
copy = super
|
563
|
-
copy.initialize_dup(self)
|
564
|
-
copy
|
565
|
-
end
|
566
|
-
end
|
567
|
-
|
568
|
-
# Populate +coder+ with attributes about this record that should be
|
569
|
-
# serialized. The structure of +coder+ defined in this method is
|
570
|
-
# guaranteed to match the structure of +coder+ passed to the +init_with+
|
571
|
-
# method.
|
572
|
-
#
|
573
|
-
# Example:
|
574
|
-
#
|
575
|
-
# class Post < ActiveRecord::Base
|
576
|
-
# end
|
577
|
-
# coder = {}
|
578
|
-
# Post.new.encode_with(coder)
|
579
|
-
# coder # => { 'id' => nil, ... }
|
580
|
-
def encode_with(coder)
|
581
|
-
coder['attributes'] = attributes
|
582
|
-
end
|
583
|
-
|
584
|
-
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
585
|
-
# is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.
|
586
|
-
#
|
587
|
-
# Note that new records are different from any other record by definition, unless the
|
588
|
-
# other record is the receiver itself. Besides, if you fetch existing records with
|
589
|
-
# +select+ and leave the ID out, you're on your own, this predicate will return false.
|
590
|
-
#
|
591
|
-
# Note also that destroying a record preserves its ID in the model instance, so deleted
|
592
|
-
# models are still comparable.
|
593
|
-
def ==(comparison_object)
|
594
|
-
super ||
|
595
|
-
comparison_object.instance_of?(self.class) &&
|
596
|
-
id.present? &&
|
597
|
-
comparison_object.id == id
|
598
|
-
end
|
599
|
-
alias :eql? :==
|
600
|
-
|
601
|
-
# Delegates to id in order to allow two records of the same type and id to work with something like:
|
602
|
-
# [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
|
603
|
-
def hash
|
604
|
-
id.hash
|
605
|
-
end
|
606
|
-
|
607
|
-
# Freeze the attributes hash such that associations are still accessible, even on destroyed records.
|
608
|
-
def freeze
|
609
|
-
@attributes.freeze; self
|
610
|
-
end
|
611
|
-
|
612
|
-
# Returns +true+ if the attributes hash has been frozen.
|
613
|
-
def frozen?
|
614
|
-
@attributes.frozen?
|
615
|
-
end
|
616
|
-
|
617
|
-
# Allows sort on objects
|
618
|
-
def <=>(other_object)
|
619
|
-
if other_object.is_a?(self.class)
|
620
|
-
self.to_key <=> other_object.to_key
|
621
|
-
else
|
622
|
-
nil
|
623
|
-
end
|
624
|
-
end
|
625
|
-
|
626
|
-
# Returns +true+ if the record is read only. Records loaded through joins with piggy-back
|
627
|
-
# attributes will be marked as read only since they cannot be saved.
|
628
|
-
def readonly?
|
629
|
-
@readonly
|
630
|
-
end
|
631
|
-
|
632
|
-
# Marks this record as read only.
|
633
|
-
def readonly!
|
634
|
-
@readonly = true
|
635
|
-
end
|
636
|
-
|
637
|
-
# Returns the contents of the record as a nicely formatted string.
|
638
|
-
def inspect
|
639
|
-
inspection = if @attributes
|
640
|
-
self.class.column_names.collect { |name|
|
641
|
-
if has_attribute?(name)
|
642
|
-
"#{name}: #{attribute_for_inspect(name)}"
|
643
|
-
end
|
644
|
-
}.compact.join(", ")
|
645
|
-
else
|
646
|
-
"not initialized"
|
647
|
-
end
|
648
|
-
"#<#{self.class} #{inspection}>"
|
649
|
-
end
|
650
|
-
|
651
|
-
# Hackery to accomodate Syck. Remove for 4.0.
|
652
|
-
def to_yaml(opts = {}) #:nodoc:
|
653
|
-
if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck?
|
654
|
-
super
|
655
|
-
else
|
656
|
-
coder = {}
|
657
|
-
encode_with(coder)
|
658
|
-
YAML.quick_emit(self, opts) do |out|
|
659
|
-
out.map(taguri, to_yaml_style) do |map|
|
660
|
-
coder.each { |k, v| map.add(k, v) }
|
661
|
-
end
|
662
|
-
end
|
663
|
-
end
|
664
|
-
end
|
665
|
-
|
666
|
-
# Hackery to accomodate Syck. Remove for 4.0.
|
667
|
-
def yaml_initialize(tag, coder) #:nodoc:
|
668
|
-
init_with(coder)
|
669
|
-
end
|
670
|
-
|
671
|
-
private
|
672
|
-
|
673
|
-
# Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements
|
674
|
-
# of the array, and then rescues from the possible NoMethodError. If those elements are
|
675
|
-
# ActiveRecord::Base's, then this triggers the various method_missing's that we have,
|
676
|
-
# which significantly impacts upon performance.
|
677
|
-
#
|
678
|
-
# So we can avoid the method_missing hit by explicitly defining #to_ary as nil here.
|
679
|
-
#
|
680
|
-
# See also http://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary/
|
681
|
-
def to_ary # :nodoc:
|
682
|
-
nil
|
683
|
-
end
|
684
|
-
|
685
|
-
include ActiveRecord::Persistence
|
686
278
|
extend ActiveModel::Naming
|
687
|
-
|
279
|
+
|
688
280
|
extend ActiveSupport::Benchmarkable
|
689
281
|
extend ActiveSupport::DescendantsTracker
|
690
282
|
|
283
|
+
extend ConnectionHandling
|
284
|
+
extend QueryCache::ClassMethods
|
691
285
|
extend Querying
|
286
|
+
extend Translation
|
287
|
+
extend DynamicMatchers
|
288
|
+
extend Explain
|
289
|
+
extend Enum
|
290
|
+
extend Delegation::DelegateCache
|
291
|
+
extend CollectionCacheKey
|
292
|
+
|
293
|
+
include Core
|
294
|
+
include Persistence
|
692
295
|
include ReadonlyAttributes
|
693
296
|
include ModelSchema
|
694
|
-
extend Translation
|
695
297
|
include Inheritance
|
696
298
|
include Scoping
|
697
|
-
extend DynamicMatchers
|
698
299
|
include Sanitization
|
699
300
|
include AttributeAssignment
|
700
301
|
include ActiveModel::Conversion
|
701
302
|
include Integration
|
702
303
|
include Validations
|
703
|
-
|
704
|
-
include
|
304
|
+
include CounterCache
|
305
|
+
include Attributes
|
306
|
+
include AttributeDecorators
|
307
|
+
include Locking::Optimistic
|
308
|
+
include Locking::Pessimistic
|
309
|
+
include DefineCallbacks
|
705
310
|
include AttributeMethods
|
706
|
-
include Callbacks
|
311
|
+
include Callbacks
|
312
|
+
include Timestamp
|
707
313
|
include Associations
|
708
|
-
include IdentityMap
|
709
314
|
include ActiveModel::SecurePassword
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
include
|
715
|
-
include
|
315
|
+
include AutosaveAssociation
|
316
|
+
include NestedAttributes
|
317
|
+
include Aggregations
|
318
|
+
include Transactions
|
319
|
+
include TouchLater
|
320
|
+
include NoTouching
|
321
|
+
include Reflection
|
322
|
+
include Serialization
|
323
|
+
include Store
|
324
|
+
include SecureToken
|
325
|
+
include Suppressor
|
716
326
|
end
|
717
|
-
end
|
718
327
|
|
719
|
-
|
720
|
-
|
328
|
+
ActiveSupport.run_load_hooks(:active_record, Base)
|
329
|
+
end
|