activerecord 4.2.0 → 4.2.11
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 -1
- data/lib/active_record.rb +3 -0
- data/lib/active_record/aggregations.rb +6 -3
- data/lib/active_record/association_relation.rb +13 -0
- data/lib/active_record/associations.rb +5 -4
- data/lib/active_record/associations/association.rb +15 -3
- data/lib/active_record/associations/association_scope.rb +1 -0
- data/lib/active_record/associations/belongs_to_association.rb +13 -5
- data/lib/active_record/associations/builder/association.rb +1 -1
- data/lib/active_record/associations/builder/collection_association.rb +5 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +8 -4
- data/lib/active_record/associations/collection_association.rb +35 -15
- data/lib/active_record/associations/collection_proxy.rb +15 -9
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +30 -15
- data/lib/active_record/associations/has_many_through_association.rb +11 -2
- data/lib/active_record/associations/has_one_association.rb +1 -0
- data/lib/active_record/associations/join_dependency.rb +8 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +7 -1
- data/lib/active_record/associations/preloader.rb +4 -4
- data/lib/active_record/associations/preloader/association.rb +5 -1
- data/lib/active_record/associations/singular_association.rb +2 -8
- data/lib/active_record/associations/through_association.rb +11 -6
- data/lib/active_record/attribute.rb +15 -1
- data/lib/active_record/attribute_assignment.rb +2 -2
- data/lib/active_record/attribute_methods.rb +4 -8
- data/lib/active_record/attribute_methods/before_type_cast.rb +5 -0
- data/lib/active_record/attribute_methods/dirty.rb +14 -4
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +5 -1
- data/lib/active_record/attribute_methods/write.rb +1 -1
- data/lib/active_record/attribute_set.rb +4 -0
- data/lib/active_record/attribute_set/builder.rb +32 -12
- data/lib/active_record/attributes.rb +8 -0
- data/lib/active_record/autosave_association.rb +24 -9
- data/lib/active_record/base.rb +4 -5
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +12 -6
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +23 -3
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +26 -16
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +87 -24
- data/lib/active_record/connection_adapters/abstract/transaction.rb +2 -6
- data/lib/active_record/connection_adapters/abstract_adapter.rb +25 -7
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +73 -10
- data/lib/active_record/connection_adapters/column.rb +2 -2
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +7 -21
- data/lib/active_record/connection_adapters/mysql_adapter.rb +10 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +17 -5
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +21 -13
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +12 -12
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +12 -28
- data/lib/active_record/connection_handling.rb +1 -1
- data/lib/active_record/core.rb +28 -15
- data/lib/active_record/counter_cache.rb +1 -1
- data/lib/active_record/enum.rb +2 -3
- data/lib/active_record/errors.rb +6 -5
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixtures.rb +9 -7
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/legacy_yaml_adapter.rb +30 -0
- data/lib/active_record/locking/optimistic.rb +16 -14
- data/lib/active_record/migration.rb +38 -10
- data/lib/active_record/model_schema.rb +4 -2
- data/lib/active_record/nested_attributes.rb +13 -3
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/persistence.rb +7 -4
- data/lib/active_record/railtie.rb +5 -3
- data/lib/active_record/railties/databases.rake +17 -24
- data/lib/active_record/reflection.rb +40 -28
- data/lib/active_record/relation.rb +3 -2
- data/lib/active_record/relation/calculations.rb +10 -3
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +4 -16
- data/lib/active_record/relation/merger.rb +24 -1
- data/lib/active_record/relation/predicate_builder.rb +32 -3
- data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -2
- data/lib/active_record/relation/query_methods.rb +29 -27
- data/lib/active_record/relation/spawn_methods.rb +7 -3
- data/lib/active_record/schema_dumper.rb +1 -1
- data/lib/active_record/schema_migration.rb +1 -4
- data/lib/active_record/scoping/default.rb +1 -0
- data/lib/active_record/tasks/database_tasks.rb +5 -2
- data/lib/active_record/tasks/mysql_database_tasks.rb +30 -16
- data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -8
- data/lib/active_record/transactions.rb +21 -11
- data/lib/active_record/type/boolean.rb +1 -0
- data/lib/active_record/type/date.rb +4 -0
- data/lib/active_record/type/date_time.rb +14 -3
- data/lib/active_record/type/decimal.rb +27 -3
- data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
- data/lib/active_record/type/integer.rb +9 -5
- data/lib/active_record/type/numeric.rb +1 -1
- data/lib/active_record/type/serialized.rb +7 -1
- data/lib/active_record/type/string.rb +4 -0
- data/lib/active_record/type/value.rb +9 -0
- data/lib/active_record/validations/uniqueness.rb +16 -6
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -6
- metadata +9 -7
@@ -94,6 +94,11 @@ module ActiveRecord
|
|
94
94
|
|
95
95
|
through_record = through_association.build(*options_for_through_record)
|
96
96
|
through_record.send("#{source_reflection.name}=", record)
|
97
|
+
|
98
|
+
if options[:source_type]
|
99
|
+
through_record.send("#{source_reflection.foreign_type}=", options[:source_type])
|
100
|
+
end
|
101
|
+
|
97
102
|
through_record
|
98
103
|
end
|
99
104
|
end
|
@@ -188,9 +193,9 @@ module ActiveRecord
|
|
188
193
|
|
189
194
|
if through_reflection.collection? && update_through_counter?(method)
|
190
195
|
update_counter(-count, through_reflection)
|
196
|
+
else
|
197
|
+
update_counter(-count)
|
191
198
|
end
|
192
|
-
|
193
|
-
update_counter(-count)
|
194
199
|
end
|
195
200
|
|
196
201
|
def through_records_for(record)
|
@@ -229,6 +234,10 @@ module ActiveRecord
|
|
229
234
|
false
|
230
235
|
end
|
231
236
|
|
237
|
+
def has_cached_counter?(reflection = reflection())
|
238
|
+
owner.attribute_present?(cached_counter_attribute_name(reflection))
|
239
|
+
end
|
240
|
+
|
232
241
|
def through_reflection_updates_counter_cache?
|
233
242
|
counter_name = cached_counter_attribute_name
|
234
243
|
inverse_updates_counter_named?(counter_name, through_reflection)
|
@@ -151,7 +151,8 @@ module ActiveRecord
|
|
151
151
|
|
152
152
|
message_bus.instrument('instantiation.active_record', payload) do
|
153
153
|
result_set.each { |row_hash|
|
154
|
-
|
154
|
+
parent_key = primary_key ? row_hash[primary_key] : row_hash
|
155
|
+
parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases)
|
155
156
|
construct(parent, join_root, row_hash, result_set, seen, model_cache, aliases)
|
156
157
|
}
|
157
158
|
end
|
@@ -233,6 +234,7 @@ module ActiveRecord
|
|
233
234
|
end
|
234
235
|
|
235
236
|
def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
|
237
|
+
return if ar_parent.nil?
|
236
238
|
primary_id = ar_parent.id
|
237
239
|
|
238
240
|
parent.children.each do |node|
|
@@ -249,7 +251,11 @@ module ActiveRecord
|
|
249
251
|
|
250
252
|
key = aliases.column_alias(node, node.primary_key)
|
251
253
|
id = row[key]
|
252
|
-
|
254
|
+
if id.nil?
|
255
|
+
nil_association = ar_parent.association(node.reflection.name)
|
256
|
+
nil_association.loaded!
|
257
|
+
next
|
258
|
+
end
|
253
259
|
|
254
260
|
model = seen[parent.base_klass][primary_id][node.base_klass][id]
|
255
261
|
|
@@ -52,7 +52,13 @@ module ActiveRecord
|
|
52
52
|
end
|
53
53
|
scope_chain_index += 1
|
54
54
|
|
55
|
-
|
55
|
+
klass_scope =
|
56
|
+
if klass.current_scope && klass.current_scope.values.blank?
|
57
|
+
klass.unscoped
|
58
|
+
else
|
59
|
+
klass.send(:build_default_scope, ActiveRecord::Relation.create(klass, table))
|
60
|
+
end
|
61
|
+
scope_chain_items.concat [klass_scope].compact
|
56
62
|
|
57
63
|
rel = scope_chain_items.inject(scope_chain_items.shift) do |left, right|
|
58
64
|
left.merge right
|
@@ -10,13 +10,13 @@ module ActiveRecord
|
|
10
10
|
# end
|
11
11
|
#
|
12
12
|
# class Book < ActiveRecord::Base
|
13
|
-
# # columns: title, sales
|
13
|
+
# # columns: title, sales, author_id
|
14
14
|
# end
|
15
15
|
#
|
16
16
|
# When you load an author with all associated books Active Record will make
|
17
17
|
# multiple queries like this:
|
18
18
|
#
|
19
|
-
# Author.includes(:books).where(:
|
19
|
+
# Author.includes(:books).where(name: ['bell hooks', 'Homer']).to_a
|
20
20
|
#
|
21
21
|
# => SELECT `authors`.* FROM `authors` WHERE `name` IN ('bell hooks', 'Homer')
|
22
22
|
# => SELECT `books`.* FROM `books` WHERE `author_id` IN (2, 5)
|
@@ -160,7 +160,7 @@ module ActiveRecord
|
|
160
160
|
h
|
161
161
|
end
|
162
162
|
|
163
|
-
class AlreadyLoaded
|
163
|
+
class AlreadyLoaded # :nodoc:
|
164
164
|
attr_reader :owners, :reflection
|
165
165
|
|
166
166
|
def initialize(klass, owners, reflection, preload_scope)
|
@@ -175,7 +175,7 @@ module ActiveRecord
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
178
|
-
class NullPreloader
|
178
|
+
class NullPreloader # :nodoc:
|
179
179
|
def self.new(klass, owners, reflection, preload_scope); self; end
|
180
180
|
def self.run(preloader); end
|
181
181
|
def self.preloaded_records; []; end
|
@@ -145,6 +145,10 @@ module ActiveRecord
|
|
145
145
|
scope.joins! preload_values[:joins] || values[:joins]
|
146
146
|
scope.order! preload_values[:order] || values[:order]
|
147
147
|
|
148
|
+
if preload_values[:reordering] || values[:reordering]
|
149
|
+
scope.reordering_value = true
|
150
|
+
end
|
151
|
+
|
148
152
|
if preload_values[:readonly] || values[:readonly]
|
149
153
|
scope.readonly!
|
150
154
|
end
|
@@ -153,7 +157,7 @@ module ActiveRecord
|
|
153
157
|
scope.where!(klass.table_name => { reflection.type => model.base_class.sti_name })
|
154
158
|
end
|
155
159
|
|
156
|
-
scope.unscope_values = Array(values[:unscope])
|
160
|
+
scope.unscope_values = Array(values[:unscope]) + Array(preload_values[:unscope])
|
157
161
|
klass.default_scoped.merge(scope)
|
158
162
|
end
|
159
163
|
end
|
@@ -3,7 +3,7 @@ module ActiveRecord
|
|
3
3
|
class SingularAssociation < Association #:nodoc:
|
4
4
|
# Implements the reader method, e.g. foo.bar for Foo.has_one :bar
|
5
5
|
def reader(force_reload = false)
|
6
|
-
if force_reload
|
6
|
+
if force_reload && klass
|
7
7
|
klass.uncached { reload }
|
8
8
|
elsif !loaded? || stale_target?
|
9
9
|
reload
|
@@ -39,13 +39,7 @@ module ActiveRecord
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def get_records
|
42
|
-
|
43
|
-
scope.eager_loading? ||
|
44
|
-
klass.current_scope ||
|
45
|
-
klass.default_scopes.any?
|
46
|
-
|
47
|
-
return scope.limit(1).to_a
|
48
|
-
end
|
42
|
+
return scope.limit(1).to_a if skip_statement_cache?
|
49
43
|
|
50
44
|
conn = klass.connection
|
51
45
|
sc = reflection.association_scope_cache(conn, owner) do
|
@@ -15,12 +15,6 @@ module ActiveRecord
|
|
15
15
|
scope = super
|
16
16
|
reflection.chain.drop(1).each do |reflection|
|
17
17
|
relation = reflection.klass.all
|
18
|
-
|
19
|
-
reflection_scope = reflection.scope
|
20
|
-
if reflection_scope && reflection_scope.arity.zero?
|
21
|
-
relation.merge!(reflection_scope)
|
22
|
-
end
|
23
|
-
|
24
18
|
scope.merge!(
|
25
19
|
relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
|
26
20
|
)
|
@@ -91,6 +85,17 @@ module ActiveRecord
|
|
91
85
|
raise HasManyThroughNestedAssociationsAreReadonly.new(owner, reflection)
|
92
86
|
end
|
93
87
|
end
|
88
|
+
|
89
|
+
def build_record(attributes)
|
90
|
+
inverse = source_reflection.inverse_of
|
91
|
+
target = through_association.target
|
92
|
+
|
93
|
+
if inverse && target && !target.is_a?(Array)
|
94
|
+
attributes[inverse.foreign_key] = target.id
|
95
|
+
end
|
96
|
+
|
97
|
+
super(attributes)
|
98
|
+
end
|
94
99
|
end
|
95
100
|
end
|
96
101
|
end
|
@@ -51,7 +51,7 @@ module ActiveRecord
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def changed_in_place_from?(old_value)
|
54
|
-
type.changed_in_place?(old_value, value)
|
54
|
+
has_been_read? && type.changed_in_place?(old_value, value)
|
55
55
|
end
|
56
56
|
|
57
57
|
def with_value_from_user(value)
|
@@ -74,6 +74,10 @@ module ActiveRecord
|
|
74
74
|
true
|
75
75
|
end
|
76
76
|
|
77
|
+
def came_from_user?
|
78
|
+
false
|
79
|
+
end
|
80
|
+
|
77
81
|
def ==(other)
|
78
82
|
self.class == other.class &&
|
79
83
|
name == other.name &&
|
@@ -89,6 +93,12 @@ module ActiveRecord
|
|
89
93
|
end
|
90
94
|
end
|
91
95
|
|
96
|
+
private
|
97
|
+
|
98
|
+
def has_been_read?
|
99
|
+
defined?(@value)
|
100
|
+
end
|
101
|
+
|
92
102
|
class FromDatabase < Attribute # :nodoc:
|
93
103
|
def type_cast(value)
|
94
104
|
type.type_cast_from_database(value)
|
@@ -99,6 +109,10 @@ module ActiveRecord
|
|
99
109
|
def type_cast(value)
|
100
110
|
type.type_cast_from_user(value)
|
101
111
|
end
|
112
|
+
|
113
|
+
def came_from_user?
|
114
|
+
true
|
115
|
+
end
|
102
116
|
end
|
103
117
|
|
104
118
|
class WithCastValue < Attribute # :nodoc:
|
@@ -52,7 +52,7 @@ module ActiveRecord
|
|
52
52
|
|
53
53
|
def _assign_attribute(k, v)
|
54
54
|
public_send("#{k}=", v)
|
55
|
-
rescue NoMethodError
|
55
|
+
rescue NoMethodError, NameError
|
56
56
|
if respond_to?("#{k}=")
|
57
57
|
raise
|
58
58
|
else
|
@@ -69,7 +69,7 @@ module ActiveRecord
|
|
69
69
|
# by calling new on the column type or aggregation type (through composed_of) object with these parameters.
|
70
70
|
# So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
|
71
71
|
# written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
|
72
|
-
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for
|
72
|
+
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and
|
73
73
|
# f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.
|
74
74
|
def assign_multiparameter_attributes(pairs)
|
75
75
|
execute_callstack_for_multiparameter_attributes(
|
@@ -287,9 +287,8 @@ module ActiveRecord
|
|
287
287
|
# Returns an <tt>#inspect</tt>-like string for the value of the
|
288
288
|
# attribute +attr_name+. String attributes are truncated up to 50
|
289
289
|
# characters, Date and Time attributes are returned in the
|
290
|
-
# <tt>:db</tt> format
|
291
|
-
#
|
292
|
-
# modification.
|
290
|
+
# <tt>:db</tt> format. Other attributes return the value of
|
291
|
+
# <tt>#inspect</tt> without modification.
|
293
292
|
#
|
294
293
|
# person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
|
295
294
|
#
|
@@ -300,7 +299,7 @@ module ActiveRecord
|
|
300
299
|
# # => "\"2012-10-22 00:15:07\""
|
301
300
|
#
|
302
301
|
# person.attribute_for_inspect(:tag_ids)
|
303
|
-
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
302
|
+
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
|
304
303
|
def attribute_for_inspect(attr_name)
|
305
304
|
value = read_attribute(attr_name)
|
306
305
|
|
@@ -308,9 +307,6 @@ module ActiveRecord
|
|
308
307
|
"#{value[0, 50]}...".inspect
|
309
308
|
elsif value.is_a?(Date) || value.is_a?(Time)
|
310
309
|
%("#{value.to_s(:db)}")
|
311
|
-
elsif value.is_a?(Array) && value.size > 10
|
312
|
-
inspected = value.first(10).inspect
|
313
|
-
%(#{inspected[0...-1]}, ...])
|
314
310
|
else
|
315
311
|
value.inspect
|
316
312
|
end
|
@@ -368,7 +364,7 @@ module ActiveRecord
|
|
368
364
|
# person = Person.new
|
369
365
|
# person[:age] = '22'
|
370
366
|
# person[:age] # => 22
|
371
|
-
# person[:age] # =>
|
367
|
+
# person[:age].class # => Integer
|
372
368
|
def []=(attr_name, value)
|
373
369
|
write_attribute(attr_name, value)
|
374
370
|
end
|
@@ -28,6 +28,7 @@ module ActiveRecord
|
|
28
28
|
|
29
29
|
included do
|
30
30
|
attribute_method_suffix "_before_type_cast"
|
31
|
+
attribute_method_suffix "_came_from_user?"
|
31
32
|
end
|
32
33
|
|
33
34
|
# Returns the value of the attribute identified by +attr_name+ before
|
@@ -66,6 +67,10 @@ module ActiveRecord
|
|
66
67
|
def attribute_before_type_cast(attribute_name)
|
67
68
|
read_attribute_before_type_cast(attribute_name)
|
68
69
|
end
|
70
|
+
|
71
|
+
def attribute_came_from_user?(attribute_name)
|
72
|
+
@attributes[attribute_name].came_from_user?
|
73
|
+
end
|
69
74
|
end
|
70
75
|
end
|
71
76
|
end
|
@@ -40,6 +40,7 @@ module ActiveRecord
|
|
40
40
|
|
41
41
|
def initialize_dup(other) # :nodoc:
|
42
42
|
super
|
43
|
+
@original_raw_attributes = nil
|
43
44
|
calculate_changes_from_defaults
|
44
45
|
end
|
45
46
|
|
@@ -76,6 +77,10 @@ module ActiveRecord
|
|
76
77
|
|
77
78
|
private
|
78
79
|
|
80
|
+
def changes_include?(attr_name)
|
81
|
+
super || attribute_changed_in_place?(attr_name)
|
82
|
+
end
|
83
|
+
|
79
84
|
def calculate_changes_from_defaults
|
80
85
|
@changed_attributes = nil
|
81
86
|
self.class.column_defaults.each do |attr, orig_value|
|
@@ -104,7 +109,8 @@ module ActiveRecord
|
|
104
109
|
end
|
105
110
|
|
106
111
|
def save_changed_attribute(attr, old_value)
|
107
|
-
|
112
|
+
clear_changed_attributes_cache
|
113
|
+
if attribute_changed_by_setter?(attr)
|
108
114
|
clear_attribute_changes(attr) unless _field_changed?(attr, old_value)
|
109
115
|
else
|
110
116
|
set_attribute_was(attr, old_value) if _field_changed?(attr, old_value)
|
@@ -130,7 +136,7 @@ module ActiveRecord
|
|
130
136
|
# Serialized attributes should always be written in case they've been
|
131
137
|
# changed in place.
|
132
138
|
def keys_for_partial_write
|
133
|
-
changed
|
139
|
+
changed & persistable_attribute_names
|
134
140
|
end
|
135
141
|
|
136
142
|
def _field_changed?(attr, old_value)
|
@@ -161,7 +167,7 @@ module ActiveRecord
|
|
161
167
|
end
|
162
168
|
|
163
169
|
def store_original_raw_attribute(attr_name)
|
164
|
-
original_raw_attributes[attr_name] = @attributes[attr_name].value_for_database
|
170
|
+
original_raw_attributes[attr_name] = @attributes[attr_name].value_for_database rescue nil
|
165
171
|
end
|
166
172
|
|
167
173
|
def store_original_raw_attributes
|
@@ -174,7 +180,11 @@ module ActiveRecord
|
|
174
180
|
@cached_changed_attributes = changed_attributes
|
175
181
|
yield
|
176
182
|
ensure
|
177
|
-
|
183
|
+
clear_changed_attributes_cache
|
184
|
+
end
|
185
|
+
|
186
|
+
def clear_changed_attributes_cache
|
187
|
+
remove_instance_variable(:@cached_changed_attributes) if defined?(@cached_changed_attributes)
|
178
188
|
end
|
179
189
|
end
|
180
190
|
end
|
@@ -12,7 +12,11 @@ module ActiveRecord
|
|
12
12
|
if value.is_a?(Array)
|
13
13
|
value.map { |v| type_cast_from_user(v) }
|
14
14
|
elsif value.respond_to?(:in_time_zone)
|
15
|
-
|
15
|
+
begin
|
16
|
+
value.in_time_zone || super
|
17
|
+
rescue ArgumentError
|
18
|
+
nil
|
19
|
+
end
|
16
20
|
end
|
17
21
|
end
|
18
22
|
|
@@ -50,7 +50,7 @@ module ActiveRecord
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# Updates the attribute identified by <tt>attr_name</tt> with the
|
53
|
-
# specified +value+. Empty strings for
|
53
|
+
# specified +value+. Empty strings for Integer and Float columns are
|
54
54
|
# turned into +nil+.
|
55
55
|
def write_attribute(attr_name, value)
|
56
56
|
write_attribute_with_type_cast(attr_name, value, true)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_record/attribute'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class AttributeSet # :nodoc:
|
3
5
|
class Builder # :nodoc:
|
@@ -20,7 +22,7 @@ module ActiveRecord
|
|
20
22
|
end
|
21
23
|
|
22
24
|
class LazyAttributeHash # :nodoc:
|
23
|
-
delegate :
|
25
|
+
delegate :transform_values, to: :materialize
|
24
26
|
|
25
27
|
def initialize(types, values, additional_types)
|
26
28
|
@types = types
|
@@ -54,10 +56,39 @@ module ActiveRecord
|
|
54
56
|
super
|
55
57
|
end
|
56
58
|
|
59
|
+
def select
|
60
|
+
keys = types.keys | values.keys | delegate_hash.keys
|
61
|
+
keys.each_with_object({}) do |key, hash|
|
62
|
+
attribute = self[key]
|
63
|
+
if yield(key, attribute)
|
64
|
+
hash[key] = attribute
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def ==(other)
|
70
|
+
if other.is_a?(LazyAttributeHash)
|
71
|
+
materialize == other.materialize
|
72
|
+
else
|
73
|
+
materialize == other
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
57
77
|
protected
|
58
78
|
|
59
79
|
attr_reader :types, :values, :additional_types, :delegate_hash
|
60
80
|
|
81
|
+
def materialize
|
82
|
+
unless @materialized
|
83
|
+
values.each_key { |key| self[key] }
|
84
|
+
types.each_key { |key| self[key] }
|
85
|
+
unless frozen?
|
86
|
+
@materialized = true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
delegate_hash
|
90
|
+
end
|
91
|
+
|
61
92
|
private
|
62
93
|
|
63
94
|
def assign_default_value(name)
|
@@ -71,16 +102,5 @@ module ActiveRecord
|
|
71
102
|
delegate_hash[name] = Attribute.uninitialized(name, type)
|
72
103
|
end
|
73
104
|
end
|
74
|
-
|
75
|
-
def materialize
|
76
|
-
unless @materialized
|
77
|
-
values.each_key { |key| self[key] }
|
78
|
-
types.each_key { |key| self[key] }
|
79
|
-
unless frozen?
|
80
|
-
@materialized = true
|
81
|
-
end
|
82
|
-
end
|
83
|
-
delegate_hash
|
84
|
-
end
|
85
105
|
end
|
86
106
|
end
|