activerecord 5.0.7.2 → 5.1.0.beta1
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 +389 -2252
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record.rb +20 -20
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations.rb +1579 -1569
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +23 -15
- data/lib/active_record/associations/association_scope.rb +83 -81
- data/lib/active_record/associations/belongs_to_association.rb +0 -1
- data/lib/active_record/associations/builder/belongs_to.rb +16 -14
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +74 -241
- data/lib/active_record/associations/collection_proxy.rb +144 -70
- data/lib/active_record/associations/has_many_association.rb +15 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -5
- data/lib/active_record/associations/has_one_association.rb +22 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency.rb +117 -115
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/preloader/association.rb +87 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +34 -41
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +3 -6
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +216 -34
- data/lib/active_record/attribute_methods/primary_key.rb +78 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +36 -30
- data/lib/active_record/attribute_mutation_tracker.rb +53 -10
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attribute_set/builder.rb +41 -49
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attributes.rb +21 -21
- data/lib/active_record/autosave_association.rb +13 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +52 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +6 -17
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
- data/lib/active_record/connection_adapters/column.rb +27 -5
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -43
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +49 -31
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +28 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +38 -36
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +161 -170
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -20
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +187 -130
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +110 -93
- data/lib/active_record/counter_cache.rb +62 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +58 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +64 -56
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +29 -29
- data/lib/active_record/migration.rb +155 -172
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +76 -37
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/model_schema.rb +85 -119
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +10 -33
- data/lib/active_record/persistence.rb +45 -38
- data/lib/active_record/query_cache.rb +4 -8
- data/lib/active_record/querying.rb +2 -3
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +125 -140
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +79 -96
- data/lib/active_record/relation.rb +72 -115
- data/lib/active_record/relation/batches.rb +87 -58
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/calculations.rb +154 -160
- data/lib/active_record/relation/delegation.rb +30 -29
- data/lib/active_record/relation/finder_methods.rb +195 -226
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +247 -295
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +79 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/result.rb +29 -31
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +182 -197
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +14 -37
- data/lib/active_record/schema_migration.rb +3 -3
- data/lib/active_record/scoping.rb +9 -10
- data/lib/active_record/scoping/default.rb +87 -91
- data/lib/active_record/scoping/named.rb +16 -28
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +72 -65
- data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
- data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +98 -110
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +9 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/serialized.rb +8 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/version.rb +1 -1
- data/lib/rails/generators/active_record.rb +4 -4
- data/lib/rails/generators/active_record/migration.rb +2 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- metadata +22 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "set"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module AttributeMethods
|
@@ -9,7 +9,7 @@ module ActiveRecord
|
|
9
9
|
# available.
|
10
10
|
def to_key
|
11
11
|
sync_with_transaction_state
|
12
|
-
key =
|
12
|
+
key = id
|
13
13
|
[key] if key
|
14
14
|
end
|
15
15
|
|
@@ -45,97 +45,102 @@ module ActiveRecord
|
|
45
45
|
attribute_was(self.class.primary_key)
|
46
46
|
end
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
attr_name == 'id' || super
|
48
|
+
def id_in_database
|
49
|
+
sync_with_transaction_state
|
50
|
+
attribute_in_database(self.class.primary_key)
|
52
51
|
end
|
53
52
|
|
54
|
-
|
55
|
-
def define_method_attribute(attr_name)
|
56
|
-
super
|
53
|
+
private
|
57
54
|
|
58
|
-
|
59
|
-
|
60
|
-
end
|
55
|
+
def attribute_method?(attr_name)
|
56
|
+
attr_name == "id" || super
|
61
57
|
end
|
62
58
|
|
63
|
-
|
59
|
+
module ClassMethods
|
60
|
+
def define_method_attribute(attr_name)
|
61
|
+
super
|
64
62
|
|
65
|
-
|
66
|
-
|
67
|
-
|
63
|
+
if attr_name == primary_key && attr_name != "id"
|
64
|
+
generated_attribute_methods.send(:alias_method, :id, primary_key)
|
65
|
+
end
|
66
|
+
end
|
68
67
|
|
69
|
-
|
70
|
-
# Overwriting will negate any effect of the +primary_key_prefix_type+
|
71
|
-
# setting, though.
|
72
|
-
def primary_key
|
73
|
-
@primary_key = reset_primary_key unless defined? @primary_key
|
74
|
-
@primary_key
|
75
|
-
end
|
68
|
+
ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast id_was id_in_database).to_set
|
76
69
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
@quoted_primary_key ||= connection.quote_column_name(primary_key)
|
81
|
-
end
|
70
|
+
def dangerous_attribute_method?(method_name)
|
71
|
+
super && !ID_ATTRIBUTE_METHODS.include?(method_name)
|
72
|
+
end
|
82
73
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
74
|
+
# Defines the primary key field -- can be overridden in subclasses.
|
75
|
+
# Overwriting will negate any effect of the +primary_key_prefix_type+
|
76
|
+
# setting, though.
|
77
|
+
def primary_key
|
78
|
+
@primary_key = reset_primary_key unless defined? @primary_key
|
79
|
+
@primary_key
|
88
80
|
end
|
89
|
-
end
|
90
81
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
82
|
+
# Returns a quoted version of the primary key name, used to construct
|
83
|
+
# SQL statements.
|
84
|
+
def quoted_primary_key
|
85
|
+
@quoted_primary_key ||= connection.quote_column_name(primary_key)
|
86
|
+
end
|
87
|
+
|
88
|
+
def reset_primary_key #:nodoc:
|
89
|
+
if self == base_class
|
90
|
+
self.primary_key = get_primary_key(base_class.name)
|
100
91
|
else
|
101
|
-
|
92
|
+
self.primary_key = base_class.primary_key
|
102
93
|
end
|
103
94
|
end
|
104
|
-
end
|
105
95
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
96
|
+
def get_primary_key(base_name) #:nodoc:
|
97
|
+
if base_name && primary_key_prefix_type == :table_name
|
98
|
+
base_name.foreign_key(false)
|
99
|
+
elsif base_name && primary_key_prefix_type == :table_name_with_underscore
|
100
|
+
base_name.foreign_key
|
101
|
+
else
|
102
|
+
if ActiveRecord::Base != self && table_exists?
|
103
|
+
pk = connection.schema_cache.primary_keys(table_name)
|
104
|
+
suppress_composite_primary_key(pk)
|
105
|
+
else
|
106
|
+
"id"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Sets the name of the primary key column.
|
112
|
+
#
|
113
|
+
# class Project < ActiveRecord::Base
|
114
|
+
# self.primary_key = 'sysid'
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# You can also define the #primary_key method yourself:
|
118
|
+
#
|
119
|
+
# class Project < ActiveRecord::Base
|
120
|
+
# def self.primary_key
|
121
|
+
# 'foo_' + super
|
122
|
+
# end
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
# Project.primary_key # => "foo_id"
|
126
|
+
def primary_key=(value)
|
127
|
+
@primary_key = value && value.to_s
|
128
|
+
@quoted_primary_key = nil
|
129
|
+
@attributes_builder = nil
|
130
|
+
end
|
126
131
|
|
127
|
-
|
132
|
+
private
|
128
133
|
|
129
|
-
|
130
|
-
|
134
|
+
def suppress_composite_primary_key(pk)
|
135
|
+
return pk unless pk.is_a?(Array)
|
131
136
|
|
132
|
-
|
133
|
-
|
137
|
+
warn <<-WARNING.strip_heredoc
|
138
|
+
WARNING: Active Record does not support composite primary key.
|
134
139
|
|
135
|
-
|
136
|
-
|
140
|
+
#{table_name} has composite primary key. Composite primary key is ignored.
|
141
|
+
WARNING
|
142
|
+
end
|
137
143
|
end
|
138
|
-
end
|
139
144
|
end
|
140
145
|
end
|
141
146
|
end
|
@@ -4,51 +4,56 @@ module ActiveRecord
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
module ClassMethods
|
7
|
-
|
7
|
+
private
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
9
|
+
# We want to generate the methods via module_eval rather than
|
10
|
+
# define_method, because define_method is slower on dispatch.
|
11
|
+
# Evaluating many similar methods may use more memory as the instruction
|
12
|
+
# sequences are duplicated and cached (in MRI). define_method may
|
13
|
+
# be slower on dispatch, but if you're careful about the closure
|
14
|
+
# created, then define_method will consume much less memory.
|
15
|
+
#
|
16
|
+
# But sometimes the database might return columns with
|
17
|
+
# characters that are not allowed in normal method names (like
|
18
|
+
# 'my_column(omg)'. So to work around this we first define with
|
19
|
+
# the __temp__ identifier, and then use alias method to rename
|
20
|
+
# it to what we want.
|
21
|
+
#
|
22
|
+
# We are also defining a constant to hold the frozen string of
|
23
|
+
# the attribute name. Using a constant means that we do not have
|
24
|
+
# to allocate an object on each call to the attribute method.
|
25
|
+
# Making it frozen means that it doesn't get duped when used to
|
26
|
+
# key the @attributes in read_attribute.
|
27
|
+
def define_method_attribute(name)
|
28
|
+
safe_name = name.unpack("h*".freeze).first
|
29
|
+
temp_method = "__temp__#{safe_name}"
|
30
30
|
|
31
|
-
|
31
|
+
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
34
|
+
def #{temp_method}
|
35
|
+
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
|
36
|
+
_read_attribute(name) { |n| missing_attribute(n, caller) }
|
37
|
+
end
|
38
|
+
STR
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
generated_attribute_methods.module_eval do
|
41
|
+
alias_method name, temp_method
|
42
|
+
undef_method temp_method
|
43
|
+
end
|
43
44
|
end
|
44
|
-
end
|
45
45
|
end
|
46
46
|
|
47
47
|
# Returns the value of the attribute identified by <tt>attr_name</tt> after
|
48
48
|
# it has been typecast (for example, "2004-12-12" in a date column is cast
|
49
49
|
# to a date object, like Date.new(2004, 12, 12)).
|
50
50
|
def read_attribute(attr_name, &block)
|
51
|
-
name = attr_name
|
51
|
+
name = if self.class.attribute_alias?(attr_name)
|
52
|
+
self.class.attribute_alias(attr_name).to_s
|
53
|
+
else
|
54
|
+
attr_name.to_s
|
55
|
+
end
|
56
|
+
|
52
57
|
name = self.class.primary_key if name == "id".freeze && self.class.primary_key
|
53
58
|
_read_attribute(name, &block)
|
54
59
|
end
|
@@ -69,7 +74,6 @@ module ActiveRecord
|
|
69
74
|
|
70
75
|
alias :attribute :_read_attribute
|
71
76
|
private :attribute
|
72
|
-
|
73
77
|
end
|
74
78
|
end
|
75
79
|
end
|
@@ -26,7 +26,7 @@ module ActiveRecord
|
|
26
26
|
# ==== Parameters
|
27
27
|
#
|
28
28
|
# * +attr_name+ - The field name that should be serialized.
|
29
|
-
# * +class_name_or_coder+ - Optional, a coder object, which responds to
|
29
|
+
# * +class_name_or_coder+ - Optional, a coder object, which responds to +.load+ and +.dump+
|
30
30
|
# or a class name that the object type should be equal to.
|
31
31
|
#
|
32
32
|
# ==== Example
|
@@ -50,12 +50,12 @@ module ActiveRecord
|
|
50
50
|
# to ensure special objects (e.g. Active Record models) are dumped correctly
|
51
51
|
# using the #as_json hook.
|
52
52
|
coder = if class_name_or_coder == ::JSON
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
53
|
+
Coders::JSON
|
54
|
+
elsif [:load, :dump].all? { |x| class_name_or_coder.respond_to?(x) }
|
55
|
+
class_name_or_coder
|
56
|
+
else
|
57
|
+
Coders::YAMLColumn.new(attr_name, class_name_or_coder)
|
58
|
+
end
|
59
59
|
|
60
60
|
decorate_attribute_type(attr_name, :serialize) do |type|
|
61
61
|
Type::Serialized.new(type, coder)
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/string/strip'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module AttributeMethods
|
5
3
|
module TimeZoneConversion
|
@@ -26,31 +24,31 @@ module ActiveRecord
|
|
26
24
|
|
27
25
|
private
|
28
26
|
|
29
|
-
|
30
|
-
|
27
|
+
def convert_time_to_time_zone(value)
|
28
|
+
return if value.nil?
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
30
|
+
if value.acts_like?(:time)
|
31
|
+
value.in_time_zone
|
32
|
+
elsif value.is_a?(::Float)
|
33
|
+
value
|
34
|
+
else
|
35
|
+
map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
|
36
|
+
end
|
38
37
|
end
|
39
|
-
end
|
40
38
|
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
def set_time_zone_without_conversion(value)
|
40
|
+
::Time.zone.local_to_utc(value).try(:in_time_zone) if value
|
41
|
+
end
|
44
42
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
43
|
+
def map_avoiding_infinite_recursion(value)
|
44
|
+
map(value) do |v|
|
45
|
+
if value.equal?(v)
|
46
|
+
nil
|
47
|
+
else
|
48
|
+
yield(v)
|
49
|
+
end
|
51
50
|
end
|
52
51
|
end
|
53
|
-
end
|
54
52
|
end
|
55
53
|
|
56
54
|
extend ActiveSupport::Concern
|
@@ -63,53 +61,32 @@ module ActiveRecord
|
|
63
61
|
self.skip_time_zone_conversion_for_attributes = []
|
64
62
|
|
65
63
|
class_attribute :time_zone_aware_types, instance_writer: false
|
66
|
-
self.time_zone_aware_types = [:datetime, :
|
64
|
+
self.time_zone_aware_types = [:datetime, :time]
|
67
65
|
end
|
68
66
|
|
69
67
|
module ClassMethods
|
70
68
|
private
|
71
69
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
70
|
+
def inherited(subclass)
|
71
|
+
super
|
72
|
+
# We need to apply this decorator here, rather than on module inclusion. The closure
|
73
|
+
# created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the
|
74
|
+
# sub class being decorated. As such, changes to `time_zone_aware_attributes`, or
|
75
|
+
# `skip_time_zone_conversion_for_attributes` would not be picked up.
|
76
|
+
subclass.class_eval do
|
77
|
+
matcher = ->(name, type) { create_time_zone_conversion_attribute?(name, type) }
|
78
|
+
decorate_matching_attribute_types(matcher, :_time_zone_conversion) do |type|
|
79
|
+
TimeZoneConverter.new(type)
|
80
|
+
end
|
81
81
|
end
|
82
82
|
end
|
83
|
-
super
|
84
|
-
end
|
85
|
-
|
86
|
-
def create_time_zone_conversion_attribute?(name, cast_type)
|
87
|
-
enabled_for_column = time_zone_aware_attributes &&
|
88
|
-
!self.skip_time_zone_conversion_for_attributes.include?(name.to_sym)
|
89
|
-
result = enabled_for_column &&
|
90
|
-
time_zone_aware_types.include?(cast_type.type)
|
91
|
-
|
92
|
-
if enabled_for_column &&
|
93
|
-
!result &&
|
94
|
-
cast_type.type == :time &&
|
95
|
-
time_zone_aware_types.include?(:not_explicitly_configured)
|
96
|
-
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
|
97
|
-
Time columns will become time zone aware in Rails 5.1. This
|
98
|
-
still causes `String`s to be parsed as if they were in `Time.zone`,
|
99
|
-
and `Time`s to be converted to `Time.zone`.
|
100
83
|
|
101
|
-
|
84
|
+
def create_time_zone_conversion_attribute?(name, cast_type)
|
85
|
+
enabled_for_column = time_zone_aware_attributes &&
|
86
|
+
!skip_time_zone_conversion_for_attributes.include?(name.to_sym)
|
102
87
|
|
103
|
-
|
104
|
-
|
105
|
-
To use the new behavior, add the following:
|
106
|
-
|
107
|
-
config.active_record.time_zone_aware_types = [:datetime, :time]
|
108
|
-
MESSAGE
|
88
|
+
enabled_for_column && time_zone_aware_types.include?(cast_type.type)
|
109
89
|
end
|
110
|
-
|
111
|
-
result
|
112
|
-
end
|
113
90
|
end
|
114
91
|
end
|
115
92
|
end
|
@@ -8,28 +8,34 @@ module ActiveRecord
|
|
8
8
|
end
|
9
9
|
|
10
10
|
module ClassMethods
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
11
|
+
private
|
12
|
+
|
13
|
+
def define_method_attribute=(name)
|
14
|
+
safe_name = name.unpack("h*".freeze).first
|
15
|
+
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
16
|
+
|
17
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
18
|
+
def __temp__#{safe_name}=(value)
|
19
|
+
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
|
20
|
+
write_attribute(name, value)
|
21
|
+
end
|
22
|
+
alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
|
23
|
+
undef_method :__temp__#{safe_name}=
|
24
|
+
STR
|
25
|
+
end
|
26
26
|
end
|
27
27
|
|
28
28
|
# Updates the attribute identified by <tt>attr_name</tt> with the
|
29
29
|
# specified +value+. Empty strings for Integer and Float columns are
|
30
30
|
# turned into +nil+.
|
31
31
|
def write_attribute(attr_name, value)
|
32
|
-
|
32
|
+
name = if self.class.attribute_alias?(attr_name)
|
33
|
+
self.class.attribute_alias(attr_name).to_s
|
34
|
+
else
|
35
|
+
attr_name.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
write_attribute_with_type_cast(name, value, true)
|
33
39
|
end
|
34
40
|
|
35
41
|
def raw_write_attribute(attr_name, value) # :nodoc:
|
@@ -37,23 +43,23 @@ module ActiveRecord
|
|
37
43
|
end
|
38
44
|
|
39
45
|
private
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
46
|
+
# Handle *= for method_missing.
|
47
|
+
def attribute=(attribute_name, value)
|
48
|
+
write_attribute(attribute_name, value)
|
49
|
+
end
|
44
50
|
|
45
|
-
|
46
|
-
|
47
|
-
|
51
|
+
def write_attribute_with_type_cast(attr_name, value, should_type_cast)
|
52
|
+
attr_name = attr_name.to_s
|
53
|
+
attr_name = self.class.primary_key if attr_name == "id" && self.class.primary_key
|
48
54
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
55
|
+
if should_type_cast
|
56
|
+
@attributes.write_from_user(attr_name, value)
|
57
|
+
else
|
58
|
+
@attributes.write_cast_value(attr_name, value)
|
59
|
+
end
|
54
60
|
|
55
|
-
|
56
|
-
|
61
|
+
value
|
62
|
+
end
|
57
63
|
end
|
58
64
|
end
|
59
65
|
end
|