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
@@ -10,9 +10,9 @@ module ActiveRecord
|
|
10
10
|
# HasManyAssociation => has_many
|
11
11
|
# HasManyThroughAssociation + ThroughAssociation => has_many :through
|
12
12
|
#
|
13
|
-
# CollectionAssociation class provides common methods to the collections
|
13
|
+
# The CollectionAssociation class provides common methods to the collections
|
14
14
|
# defined by +has_and_belongs_to_many+, +has_many+ or +has_many+ with
|
15
|
-
# +:through association+ option.
|
15
|
+
# the +:through association+ option.
|
16
16
|
#
|
17
17
|
# You need to be careful with assumptions regarding the target: The proxy
|
18
18
|
# does not fetch records from the database until it needs them, but new
|
@@ -24,23 +24,13 @@ module ActiveRecord
|
|
24
24
|
# If you need to work on all current children, new and existing records,
|
25
25
|
# +load_target+ and the +loaded+ flag are your friends.
|
26
26
|
class CollectionAssociation < Association #:nodoc:
|
27
|
-
|
28
27
|
# Implements the reader method, e.g. foo.items for Foo.has_many :items
|
29
|
-
def reader
|
30
|
-
if
|
31
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
32
|
-
Passing an argument to force an association to reload is now
|
33
|
-
deprecated and will be removed in Rails 5.1. Please call `reload`
|
34
|
-
on the result collection proxy instead.
|
35
|
-
MSG
|
36
|
-
|
37
|
-
klass.uncached { reload }
|
38
|
-
elsif stale_target?
|
28
|
+
def reader
|
29
|
+
if stale_target?
|
39
30
|
reload
|
40
31
|
end
|
41
32
|
|
42
|
-
|
43
|
-
@proxy.reset_scope
|
33
|
+
CollectionProxy.create(klass, self)
|
44
34
|
end
|
45
35
|
|
46
36
|
# Implements the writer method, e.g. foo.items= for Foo.has_many :items
|
@@ -51,9 +41,7 @@ module ActiveRecord
|
|
51
41
|
# Implements the ids reader method, e.g. foo.item_ids for Foo.has_many :items
|
52
42
|
def ids_reader
|
53
43
|
if loaded?
|
54
|
-
|
55
|
-
record.send(reflection.association_primary_key)
|
56
|
-
end
|
44
|
+
target.pluck(reflection.association_primary_key)
|
57
45
|
else
|
58
46
|
@association_ids ||= (
|
59
47
|
column = "#{reflection.quoted_table_name}.#{reflection.association_primary_key}"
|
@@ -67,14 +55,11 @@ module ActiveRecord
|
|
67
55
|
pk_type = reflection.association_primary_key_type
|
68
56
|
ids = Array(ids).reject(&:blank?)
|
69
57
|
ids.map! { |i| pk_type.cast(i) }
|
70
|
-
|
71
|
-
|
72
|
-
records = klass.where(primary_key => ids).index_by do |r|
|
73
|
-
r.public_send(primary_key)
|
58
|
+
records = klass.where(reflection.association_primary_key => ids).index_by do |r|
|
59
|
+
r.send(reflection.association_primary_key)
|
74
60
|
end.values_at(*ids).compact
|
75
|
-
|
76
61
|
if records.size != ids.size
|
77
|
-
klass.all.raise_record_not_found_exception!(ids, records.size, ids.size,
|
62
|
+
klass.all.raise_record_not_found_exception!(ids, records.size, ids.size, reflection.association_primary_key)
|
78
63
|
else
|
79
64
|
replace(records)
|
80
65
|
end
|
@@ -85,14 +70,6 @@ module ActiveRecord
|
|
85
70
|
@target = []
|
86
71
|
end
|
87
72
|
|
88
|
-
def select(*fields)
|
89
|
-
if block_given?
|
90
|
-
load_target.select.each { |e| yield e }
|
91
|
-
else
|
92
|
-
scope.select(*fields)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
73
|
def find(*args)
|
97
74
|
if block_given?
|
98
75
|
load_target.find(*args) { |*block_args| yield(*block_args) }
|
@@ -114,52 +91,6 @@ module ActiveRecord
|
|
114
91
|
end
|
115
92
|
end
|
116
93
|
|
117
|
-
def first(*args)
|
118
|
-
first_nth_or_last(:first, *args)
|
119
|
-
end
|
120
|
-
|
121
|
-
def second(*args)
|
122
|
-
first_nth_or_last(:second, *args)
|
123
|
-
end
|
124
|
-
|
125
|
-
def third(*args)
|
126
|
-
first_nth_or_last(:third, *args)
|
127
|
-
end
|
128
|
-
|
129
|
-
def fourth(*args)
|
130
|
-
first_nth_or_last(:fourth, *args)
|
131
|
-
end
|
132
|
-
|
133
|
-
def fifth(*args)
|
134
|
-
first_nth_or_last(:fifth, *args)
|
135
|
-
end
|
136
|
-
|
137
|
-
def forty_two(*args)
|
138
|
-
first_nth_or_last(:forty_two, *args)
|
139
|
-
end
|
140
|
-
|
141
|
-
def third_to_last(*args)
|
142
|
-
first_nth_or_last(:third_to_last, *args)
|
143
|
-
end
|
144
|
-
|
145
|
-
def second_to_last(*args)
|
146
|
-
first_nth_or_last(:second_to_last, *args)
|
147
|
-
end
|
148
|
-
|
149
|
-
def last(*args)
|
150
|
-
first_nth_or_last(:last, *args)
|
151
|
-
end
|
152
|
-
|
153
|
-
def take(n = nil)
|
154
|
-
if loaded?
|
155
|
-
n ? target.take(n) : target.first
|
156
|
-
else
|
157
|
-
scope.take(n).tap do |record|
|
158
|
-
set_inverse_instance record if record.is_a? ActiveRecord::Base
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
94
|
def build(attributes = {}, &block)
|
164
95
|
if attributes.is_a?(Array)
|
165
96
|
attributes.collect { |attr| build(attr, &block) }
|
@@ -170,14 +101,6 @@ module ActiveRecord
|
|
170
101
|
end
|
171
102
|
end
|
172
103
|
|
173
|
-
def create(attributes = {}, &block)
|
174
|
-
_create_record(attributes, &block)
|
175
|
-
end
|
176
|
-
|
177
|
-
def create!(attributes = {}, &block)
|
178
|
-
_create_record(attributes, true, &block)
|
179
|
-
end
|
180
|
-
|
181
104
|
# Add +records+ to this association. Returns +self+ so method calls may
|
182
105
|
# be chained. Since << flattens its argument list and inserts each record,
|
183
106
|
# +push+ and +concat+ behave identically.
|
@@ -225,12 +148,12 @@ module ActiveRecord
|
|
225
148
|
end
|
226
149
|
|
227
150
|
dependent = if dependent
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
151
|
+
dependent
|
152
|
+
elsif options[:dependent] == :destroy
|
153
|
+
:delete_all
|
154
|
+
else
|
155
|
+
options[:dependent]
|
156
|
+
end
|
234
157
|
|
235
158
|
delete_or_nullify_all_records(dependent).tap do
|
236
159
|
reset
|
@@ -248,28 +171,6 @@ module ActiveRecord
|
|
248
171
|
end
|
249
172
|
end
|
250
173
|
|
251
|
-
# Count all records using SQL. Construct options and pass them with
|
252
|
-
# scope to the target class's +count+.
|
253
|
-
def count(column_name = nil)
|
254
|
-
relation = scope
|
255
|
-
if association_scope.distinct_value
|
256
|
-
# This is needed because 'SELECT count(DISTINCT *)..' is not valid SQL.
|
257
|
-
column_name ||= reflection.klass.primary_key
|
258
|
-
relation = relation.distinct
|
259
|
-
end
|
260
|
-
|
261
|
-
value = relation.count(column_name)
|
262
|
-
|
263
|
-
limit = options[:limit]
|
264
|
-
offset = options[:offset]
|
265
|
-
|
266
|
-
if limit || offset
|
267
|
-
[ [value - offset.to_i, 0].max, limit.to_i ].min
|
268
|
-
else
|
269
|
-
value
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
174
|
# Removes +records+ from this association calling +before_remove+ and
|
274
175
|
# +after_remove+ callbacks.
|
275
176
|
#
|
@@ -279,11 +180,8 @@ module ActiveRecord
|
|
279
180
|
# +delete_records+. They are in any case removed from the collection.
|
280
181
|
def delete(*records)
|
281
182
|
return if records.empty?
|
282
|
-
_options = records.extract_options!
|
283
|
-
dependent = _options[:dependent] || options[:dependent]
|
284
|
-
|
285
183
|
records = find(records) if records.any? { |record| record.kind_of?(Integer) || record.kind_of?(String) }
|
286
|
-
delete_or_destroy(records, dependent)
|
184
|
+
delete_or_destroy(records, options[:dependent])
|
287
185
|
end
|
288
186
|
|
289
187
|
# Deletes the +records+ and removes them from this association calling
|
@@ -309,11 +207,7 @@ module ActiveRecord
|
|
309
207
|
# +count_records+, which is a method descendants have to provide.
|
310
208
|
def size
|
311
209
|
if !find_target? || loaded?
|
312
|
-
|
313
|
-
target.uniq.size
|
314
|
-
else
|
315
|
-
target.size
|
316
|
-
end
|
210
|
+
target.size
|
317
211
|
elsif !association_scope.group_values.empty?
|
318
212
|
load_target.size
|
319
213
|
elsif !association_scope.distinct_value && target.is_a?(Array)
|
@@ -324,15 +218,6 @@ module ActiveRecord
|
|
324
218
|
end
|
325
219
|
end
|
326
220
|
|
327
|
-
# Returns the size of the collection calling +size+ on the target.
|
328
|
-
#
|
329
|
-
# If the collection has been already loaded +length+ and +size+ are
|
330
|
-
# equivalent. If not and you are going to need the records anyway this
|
331
|
-
# method will take one less query. Otherwise +size+ is more efficient.
|
332
|
-
def length
|
333
|
-
load_target.size
|
334
|
-
end
|
335
|
-
|
336
221
|
# Returns true if the collection is empty.
|
337
222
|
#
|
338
223
|
# If the collection has been loaded
|
@@ -349,36 +234,6 @@ module ActiveRecord
|
|
349
234
|
end
|
350
235
|
end
|
351
236
|
|
352
|
-
# Returns true if the collections is not empty.
|
353
|
-
# If block given, loads all records and checks for one or more matches.
|
354
|
-
# Otherwise, equivalent to +!collection.empty?+.
|
355
|
-
def any?
|
356
|
-
if block_given?
|
357
|
-
load_target.any? { |*block_args| yield(*block_args) }
|
358
|
-
else
|
359
|
-
!empty?
|
360
|
-
end
|
361
|
-
end
|
362
|
-
|
363
|
-
# Returns true if the collection has more than 1 record.
|
364
|
-
# If block given, loads all records and checks for two or more matches.
|
365
|
-
# Otherwise, equivalent to +collection.size > 1+.
|
366
|
-
def many?
|
367
|
-
if block_given?
|
368
|
-
load_target.many? { |*block_args| yield(*block_args) }
|
369
|
-
else
|
370
|
-
size > 1
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
def distinct
|
375
|
-
seen = {}
|
376
|
-
load_target.find_all do |record|
|
377
|
-
seen[record.id] = true unless seen.key?(record.id)
|
378
|
-
end
|
379
|
-
end
|
380
|
-
alias uniq distinct
|
381
|
-
|
382
237
|
# Replace this collection with +other_array+. This will perform a diff
|
383
238
|
# and delete/add only records that have changed.
|
384
239
|
def replace(other_array)
|
@@ -425,6 +280,35 @@ module ActiveRecord
|
|
425
280
|
replace_on_target(record, index, skip_callbacks, &block)
|
426
281
|
end
|
427
282
|
|
283
|
+
def replace_on_target(record, index, skip_callbacks)
|
284
|
+
callback(:before_add, record) unless skip_callbacks
|
285
|
+
|
286
|
+
begin
|
287
|
+
if index
|
288
|
+
record_was = target[index]
|
289
|
+
target[index] = record
|
290
|
+
else
|
291
|
+
target << record
|
292
|
+
end
|
293
|
+
|
294
|
+
set_inverse_instance(record)
|
295
|
+
|
296
|
+
yield(record) if block_given?
|
297
|
+
rescue
|
298
|
+
if index
|
299
|
+
target[index] = record_was
|
300
|
+
else
|
301
|
+
target.delete(record)
|
302
|
+
end
|
303
|
+
|
304
|
+
raise
|
305
|
+
end
|
306
|
+
|
307
|
+
callback(:after_add, record) unless skip_callbacks
|
308
|
+
|
309
|
+
record
|
310
|
+
end
|
311
|
+
|
428
312
|
def scope
|
429
313
|
scope = super
|
430
314
|
scope.none! if null_scope?
|
@@ -435,24 +319,27 @@ module ActiveRecord
|
|
435
319
|
owner.new_record? && !foreign_key_present?
|
436
320
|
end
|
437
321
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
conn = klass.connection
|
443
|
-
sc = reflection.association_scope_cache(conn, owner) do
|
444
|
-
StatementCache.create(conn) { |params|
|
445
|
-
as = AssociationScope.create { params.bind }
|
446
|
-
target_scope.merge as.scope(self, conn)
|
447
|
-
}
|
448
|
-
end
|
449
|
-
|
450
|
-
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
451
|
-
sc.execute(binds, klass, klass.connection, &block)
|
322
|
+
def find_from_target?
|
323
|
+
loaded? ||
|
324
|
+
owner.new_record? ||
|
325
|
+
target.any? { |record| record.new_record? || record.changed? }
|
452
326
|
end
|
453
327
|
|
328
|
+
private
|
329
|
+
|
454
330
|
def find_target
|
455
|
-
|
331
|
+
return scope.to_a if skip_statement_cache?
|
332
|
+
|
333
|
+
conn = klass.connection
|
334
|
+
sc = reflection.association_scope_cache(conn, owner) do
|
335
|
+
StatementCache.create(conn) { |params|
|
336
|
+
as = AssociationScope.create { params.bind }
|
337
|
+
target_scope.merge as.scope(self, conn)
|
338
|
+
}
|
339
|
+
end
|
340
|
+
|
341
|
+
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
342
|
+
sc.execute(binds, klass, conn) do |record|
|
456
343
|
set_inverse_instance(record)
|
457
344
|
end
|
458
345
|
end
|
@@ -474,7 +361,7 @@ module ActiveRecord
|
|
474
361
|
persisted.map! do |record|
|
475
362
|
if mem_record = memory.delete(record)
|
476
363
|
|
477
|
-
((record.attribute_names & mem_record.attribute_names) - mem_record.
|
364
|
+
((record.attribute_names & mem_record.attribute_names) - mem_record.changed_attribute_names_to_save).each do |name|
|
478
365
|
mem_record[name] = record[name]
|
479
366
|
end
|
480
367
|
|
@@ -498,19 +385,15 @@ module ActiveRecord
|
|
498
385
|
transaction do
|
499
386
|
add_to_target(build_record(attributes)) do |record|
|
500
387
|
yield(record) if block_given?
|
501
|
-
insert_record(record, true, raise)
|
388
|
+
insert_record(record, true, raise)
|
502
389
|
end
|
503
390
|
end
|
504
391
|
end
|
505
392
|
end
|
506
393
|
|
507
394
|
# Do the relevant stuff to insert the given record into the association collection.
|
508
|
-
def insert_record(record, validate = true, raise = false
|
509
|
-
|
510
|
-
record.save!(validate: validate, &block)
|
511
|
-
else
|
512
|
-
record.save(validate: validate, &block)
|
513
|
-
end
|
395
|
+
def insert_record(record, validate = true, raise = false)
|
396
|
+
raise NotImplementedError
|
514
397
|
end
|
515
398
|
|
516
399
|
def create_scope
|
@@ -538,8 +421,9 @@ module ActiveRecord
|
|
538
421
|
records.each { |record| callback(:after_remove, record) }
|
539
422
|
end
|
540
423
|
|
541
|
-
# Delete the given records from the association,
|
542
|
-
#
|
424
|
+
# Delete the given records from the association,
|
425
|
+
# using one of the methods +:destroy+, +:delete_all+
|
426
|
+
# or +:nullify+ (or +nil+, in which case a default is used).
|
543
427
|
def delete_records(records, method)
|
544
428
|
raise NotImplementedError
|
545
429
|
end
|
@@ -564,41 +448,19 @@ module ActiveRecord
|
|
564
448
|
end
|
565
449
|
end
|
566
450
|
|
567
|
-
def concat_records(records,
|
451
|
+
def concat_records(records, should_raise = false)
|
568
452
|
result = true
|
569
453
|
|
570
454
|
records.each do |record|
|
571
455
|
raise_on_type_mismatch!(record)
|
572
|
-
add_to_target(record) do
|
573
|
-
result &&= insert_record(
|
456
|
+
add_to_target(record) do |rec|
|
457
|
+
result &&= insert_record(rec, true, should_raise) unless owner.new_record?
|
574
458
|
end
|
575
459
|
end
|
576
460
|
|
577
461
|
result && records
|
578
462
|
end
|
579
463
|
|
580
|
-
def replace_on_target(record, index, skip_callbacks)
|
581
|
-
callback(:before_add, record) unless skip_callbacks
|
582
|
-
|
583
|
-
set_inverse_instance(record)
|
584
|
-
|
585
|
-
@_was_loaded = true
|
586
|
-
|
587
|
-
yield(record) if block_given?
|
588
|
-
|
589
|
-
if index
|
590
|
-
target[index] = record
|
591
|
-
elsif @_was_loaded || !loaded?
|
592
|
-
target << record
|
593
|
-
end
|
594
|
-
|
595
|
-
callback(:after_add, record) unless skip_callbacks
|
596
|
-
|
597
|
-
record
|
598
|
-
ensure
|
599
|
-
@_was_loaded = nil
|
600
|
-
end
|
601
|
-
|
602
464
|
def callback(method, record)
|
603
465
|
callbacks_for(method).each do |callback|
|
604
466
|
callback.call(method, owner, record)
|
@@ -610,25 +472,6 @@ module ActiveRecord
|
|
610
472
|
owner.class.send(full_callback_name)
|
611
473
|
end
|
612
474
|
|
613
|
-
# Should we deal with assoc.first or assoc.last by issuing an independent query to
|
614
|
-
# the database, or by getting the target, and then taking the first/last item from that?
|
615
|
-
#
|
616
|
-
# If the args is just a non-empty options hash, go to the database.
|
617
|
-
#
|
618
|
-
# Otherwise, go to the database only if none of the following are true:
|
619
|
-
# * target already loaded
|
620
|
-
# * owner is new record
|
621
|
-
# * target contains new or changed record(s)
|
622
|
-
def fetch_first_nth_or_last_using_find?(args)
|
623
|
-
if args.first.is_a?(Hash)
|
624
|
-
true
|
625
|
-
else
|
626
|
-
!(loaded? ||
|
627
|
-
owner.new_record? ||
|
628
|
-
target.any? { |record| record.new_record? || record.changed? })
|
629
|
-
end
|
630
|
-
end
|
631
|
-
|
632
475
|
def include_in_memory?(record)
|
633
476
|
if reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
|
634
477
|
assoc = owner.association(reflection.through_reflection.name)
|
@@ -655,16 +498,6 @@ module ActiveRecord
|
|
655
498
|
load_target.select { |r| ids.include?(r.id.to_s) }
|
656
499
|
end
|
657
500
|
end
|
658
|
-
|
659
|
-
# Fetches the first/last using SQL if possible, otherwise from the target array.
|
660
|
-
def first_nth_or_last(type, *args)
|
661
|
-
args.shift if args.first.is_a?(Hash) && args.first.empty?
|
662
|
-
|
663
|
-
collection = fetch_first_nth_or_last_using_find?(args) ? scope : load_target
|
664
|
-
collection.send(type, *args).tap do |record|
|
665
|
-
set_inverse_instance record if record.is_a? ActiveRecord::Base
|
666
|
-
end
|
667
|
-
end
|
668
501
|
end
|
669
502
|
end
|
670
503
|
end
|