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
@@ -11,12 +11,12 @@ module ActiveRecord
|
|
11
11
|
# Attributes listed as readonly will be used to create a new record but update operations will
|
12
12
|
# ignore these fields.
|
13
13
|
def attr_readonly(*attributes)
|
14
|
-
self._attr_readonly = Set.new(attributes.map(&:to_s)) + (
|
14
|
+
self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
|
15
15
|
end
|
16
16
|
|
17
17
|
# Returns an array of all the attributes that have been specified as readonly.
|
18
18
|
def readonly_attributes
|
19
|
-
|
19
|
+
_attr_readonly
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "thread"
|
2
|
+
require "active_support/core_ext/string/filters"
|
3
|
+
require "active_support/deprecation"
|
3
4
|
|
4
5
|
module ActiveRecord
|
5
6
|
# = Active Record Reflection
|
@@ -14,18 +15,19 @@ module ActiveRecord
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def self.create(macro, name, scope, options, ar)
|
17
|
-
klass =
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
18
|
+
klass = \
|
19
|
+
case macro
|
20
|
+
when :composed_of
|
21
|
+
AggregateReflection
|
22
|
+
when :has_many
|
23
|
+
HasManyReflection
|
24
|
+
when :has_one
|
25
|
+
HasOneReflection
|
26
|
+
when :belongs_to
|
27
|
+
BelongsToReflection
|
28
|
+
else
|
29
|
+
raise "Unsupported Macro: #{macro}"
|
30
|
+
end
|
29
31
|
|
30
32
|
reflection = klass.new(name, scope, options, ar)
|
31
33
|
options[:through] ? ThroughReflection.new(reflection) : reflection
|
@@ -135,8 +137,8 @@ module ActiveRecord
|
|
135
137
|
# BelongsToReflection
|
136
138
|
# HasAndBelongsToManyReflection
|
137
139
|
# ThroughReflection
|
138
|
-
#
|
139
|
-
#
|
140
|
+
# PolymorphicReflection
|
141
|
+
# RuntimeReflection
|
140
142
|
class AbstractReflection # :nodoc:
|
141
143
|
def through_reflection?
|
142
144
|
false
|
@@ -174,8 +176,19 @@ module ActiveRecord
|
|
174
176
|
JoinKeys.new(foreign_key, active_record_primary_key)
|
175
177
|
end
|
176
178
|
|
179
|
+
# Returns a list of scopes that should be applied for this Reflection
|
180
|
+
# object when querying the database.
|
181
|
+
def scopes
|
182
|
+
scope ? [scope] : []
|
183
|
+
end
|
184
|
+
|
185
|
+
def scope_chain
|
186
|
+
chain.map(&:scopes)
|
187
|
+
end
|
188
|
+
deprecate :scope_chain
|
189
|
+
|
177
190
|
def constraints
|
178
|
-
|
191
|
+
chain.map(&:scopes).flatten
|
179
192
|
end
|
180
193
|
|
181
194
|
def counter_cache_column
|
@@ -281,7 +294,6 @@ module ActiveRecord
|
|
281
294
|
end
|
282
295
|
|
283
296
|
def autosave=(autosave)
|
284
|
-
@automatic_inverse_of = false
|
285
297
|
@options[:autosave] = autosave
|
286
298
|
parent_reflection = self.parent_reflection
|
287
299
|
if parent_reflection
|
@@ -321,8 +333,7 @@ module ActiveRecord
|
|
321
333
|
end
|
322
334
|
end
|
323
335
|
|
324
|
-
|
325
|
-
# Holds all the meta-data about an aggregation as it was specified in the
|
336
|
+
# Holds all the metadata about an aggregation as it was specified in the
|
326
337
|
# Active Record class.
|
327
338
|
class AggregateReflection < MacroReflection #:nodoc:
|
328
339
|
def mapping
|
@@ -331,7 +342,7 @@ module ActiveRecord
|
|
331
342
|
end
|
332
343
|
end
|
333
344
|
|
334
|
-
# Holds all the
|
345
|
+
# Holds all the metadata about an association as it was specified in the
|
335
346
|
# Active Record class.
|
336
347
|
class AssociationReflection < MacroReflection #:nodoc:
|
337
348
|
# Returns the target association's class.
|
@@ -365,6 +376,17 @@ module ActiveRecord
|
|
365
376
|
@constructable = calculate_constructable(macro, options)
|
366
377
|
@association_scope_cache = {}
|
367
378
|
@scope_lock = Mutex.new
|
379
|
+
|
380
|
+
if options[:class_name] && options[:class_name].class == Class
|
381
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
382
|
+
Passing a class to the `class_name` is deprecated and will raise
|
383
|
+
an ArgumentError in Rails 5.2. It eagerloads more classes than
|
384
|
+
necessary and potentially creates circular dependencies.
|
385
|
+
|
386
|
+
Please pass the class name as a string:
|
387
|
+
`#{macro} :#{name}, class_name: '#{options[:class_name]}'`
|
388
|
+
MSG
|
389
|
+
end
|
368
390
|
end
|
369
391
|
|
370
392
|
def association_scope_cache(conn, owner)
|
@@ -451,12 +473,6 @@ module ActiveRecord
|
|
451
473
|
false
|
452
474
|
end
|
453
475
|
|
454
|
-
# An array of arrays of scopes. Each item in the outside array corresponds to a reflection
|
455
|
-
# in the #chain.
|
456
|
-
def scope_chain
|
457
|
-
scope ? [[scope]] : [[]]
|
458
|
-
end
|
459
|
-
|
460
476
|
def has_scope?
|
461
477
|
scope
|
462
478
|
end
|
@@ -527,10 +543,6 @@ module ActiveRecord
|
|
527
543
|
seed + [self]
|
528
544
|
end
|
529
545
|
|
530
|
-
def extensions
|
531
|
-
Array(options[:extend])
|
532
|
-
end
|
533
|
-
|
534
546
|
protected
|
535
547
|
|
536
548
|
def actual_source_reflection # FIXME: this is a horrible name
|
@@ -545,14 +557,10 @@ module ActiveRecord
|
|
545
557
|
|
546
558
|
# Attempts to find the inverse association name automatically.
|
547
559
|
# If it cannot find a suitable inverse association name, it returns
|
548
|
-
# nil
|
560
|
+
# +nil+.
|
549
561
|
def inverse_name
|
550
562
|
options.fetch(:inverse_of) do
|
551
|
-
|
552
|
-
nil
|
553
|
-
else
|
554
|
-
@automatic_inverse_of ||= automatic_inverse_of
|
555
|
-
end
|
563
|
+
@automatic_inverse_of ||= automatic_inverse_of
|
556
564
|
end
|
557
565
|
end
|
558
566
|
|
@@ -644,10 +652,6 @@ module ActiveRecord
|
|
644
652
|
Associations::HasManyAssociation
|
645
653
|
end
|
646
654
|
end
|
647
|
-
|
648
|
-
def association_primary_key(klass = nil)
|
649
|
-
primary_key(klass || self.klass)
|
650
|
-
end
|
651
655
|
end
|
652
656
|
|
653
657
|
class HasOneReflection < AssociationReflection # :nodoc:
|
@@ -711,16 +715,16 @@ module ActiveRecord
|
|
711
715
|
end
|
712
716
|
end
|
713
717
|
|
714
|
-
# Holds all the
|
718
|
+
# Holds all the metadata about a :through association as it was specified
|
715
719
|
# in the Active Record class.
|
716
720
|
class ThroughReflection < AbstractReflection #:nodoc:
|
717
721
|
attr_reader :delegate_reflection
|
718
722
|
delegate :foreign_key, :foreign_type, :association_foreign_key,
|
719
|
-
:active_record_primary_key, :type, :
|
723
|
+
:active_record_primary_key, :type, to: :source_reflection
|
720
724
|
|
721
725
|
def initialize(delegate_reflection)
|
722
726
|
@delegate_reflection = delegate_reflection
|
723
|
-
@klass
|
727
|
+
@klass = delegate_reflection.options[:anonymous_class]
|
724
728
|
@source_reflection_name = delegate_reflection.options[:source]
|
725
729
|
end
|
726
730
|
|
@@ -798,45 +802,12 @@ module ActiveRecord
|
|
798
802
|
through_reflection.clear_association_scope_cache
|
799
803
|
end
|
800
804
|
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
# has_many :articles
|
805
|
-
# has_many :comment_tags, through: :articles
|
806
|
-
# end
|
807
|
-
#
|
808
|
-
# class Article
|
809
|
-
# has_many :comments
|
810
|
-
# has_many :comment_tags, through: :comments, source: :tags
|
811
|
-
# end
|
812
|
-
#
|
813
|
-
# class Comment
|
814
|
-
# has_many :tags
|
815
|
-
# end
|
816
|
-
#
|
817
|
-
# There may be scopes on Person.comment_tags, Article.comment_tags and/or Comment.tags,
|
818
|
-
# but only Comment.tags will be represented in the #chain. So this method creates an array
|
819
|
-
# of scopes corresponding to the chain.
|
820
|
-
def scope_chain
|
821
|
-
@scope_chain ||= begin
|
822
|
-
scope_chain = source_reflection.scope_chain.map(&:dup)
|
823
|
-
|
824
|
-
# Add to it the scope from this reflection (if any)
|
825
|
-
scope_chain.first << scope if scope
|
826
|
-
|
827
|
-
through_scope_chain = through_reflection.scope_chain.map(&:dup)
|
828
|
-
|
829
|
-
if options[:source_type]
|
830
|
-
type = foreign_type
|
831
|
-
source_type = options[:source_type]
|
832
|
-
through_scope_chain.first << lambda { |object|
|
833
|
-
where(type => source_type)
|
834
|
-
}
|
835
|
-
end
|
805
|
+
def scopes
|
806
|
+
source_reflection.scopes + super
|
807
|
+
end
|
836
808
|
|
837
|
-
|
838
|
-
|
839
|
-
end
|
809
|
+
def source_type_scope
|
810
|
+
through_reflection.klass.where(foreign_type => options[:source_type])
|
840
811
|
end
|
841
812
|
|
842
813
|
def has_scope?
|
@@ -891,15 +862,13 @@ module ActiveRecord
|
|
891
862
|
}
|
892
863
|
|
893
864
|
if names.length > 1
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
" #{macro} :#{name}, #{example_options}\n" \
|
902
|
-
" end"
|
865
|
+
raise AmbiguousSourceReflectionForThroughAssociation.new(
|
866
|
+
active_record.name,
|
867
|
+
macro,
|
868
|
+
name,
|
869
|
+
options,
|
870
|
+
source_reflection_names
|
871
|
+
)
|
903
872
|
end
|
904
873
|
|
905
874
|
@source_reflection_name = names.first
|
@@ -946,6 +915,14 @@ module ActiveRecord
|
|
946
915
|
raise HasOneThroughCantAssociateThroughCollection.new(active_record.name, self, through_reflection)
|
947
916
|
end
|
948
917
|
|
918
|
+
if parent_reflection.nil?
|
919
|
+
reflections = active_record.reflections.keys.map(&:to_sym)
|
920
|
+
|
921
|
+
if reflections.index(through_reflection.name) > reflections.index(name)
|
922
|
+
raise HasManyThroughOrderError.new(active_record.name, self, through_reflection)
|
923
|
+
end
|
924
|
+
end
|
925
|
+
|
949
926
|
check_validity_of_inverse!
|
950
927
|
end
|
951
928
|
|
@@ -976,8 +953,7 @@ module ActiveRecord
|
|
976
953
|
end
|
977
954
|
end
|
978
955
|
|
979
|
-
|
980
|
-
|
956
|
+
private
|
981
957
|
def actual_source_reflection # FIXME: this is a horrible name
|
982
958
|
source_reflection.send(:actual_source_reflection)
|
983
959
|
end
|
@@ -988,7 +964,6 @@ module ActiveRecord
|
|
988
964
|
|
989
965
|
def inverse_name; delegate_reflection.send(:inverse_name); end
|
990
966
|
|
991
|
-
private
|
992
967
|
def derive_class_name
|
993
968
|
# get the class_name of the belongs_to association of the through reflection
|
994
969
|
options[:source_type] || source_reflection.class_name
|
@@ -998,15 +973,23 @@ module ActiveRecord
|
|
998
973
|
public_instance_methods
|
999
974
|
|
1000
975
|
delegate(*delegate_methods, to: :delegate_reflection)
|
1001
|
-
|
1002
976
|
end
|
1003
977
|
|
1004
|
-
class PolymorphicReflection <
|
978
|
+
class PolymorphicReflection < AbstractReflection # :nodoc:
|
1005
979
|
def initialize(reflection, previous_reflection)
|
1006
980
|
@reflection = reflection
|
1007
981
|
@previous_reflection = previous_reflection
|
1008
982
|
end
|
1009
983
|
|
984
|
+
def scopes
|
985
|
+
scopes = @previous_reflection.scopes
|
986
|
+
if @previous_reflection.options[:source_type]
|
987
|
+
scopes + [@previous_reflection.source_type_scope]
|
988
|
+
else
|
989
|
+
scopes
|
990
|
+
end
|
991
|
+
end
|
992
|
+
|
1010
993
|
def klass
|
1011
994
|
@reflection.klass
|
1012
995
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require "arel/collectors/bind"
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
# = Active Record \Relation
|
5
3
|
class Relation
|
@@ -31,9 +29,7 @@ module ActiveRecord
|
|
31
29
|
end
|
32
30
|
|
33
31
|
def initialize_copy(other)
|
34
|
-
|
35
|
-
# https://bugs.ruby-lang.org/issues/7166
|
36
|
-
@values = Hash[@values]
|
32
|
+
@values = @values.dup
|
37
33
|
reset
|
38
34
|
end
|
39
35
|
|
@@ -64,8 +60,8 @@ module ActiveRecord
|
|
64
60
|
|
65
61
|
@klass.connection.insert(
|
66
62
|
im,
|
67
|
-
|
68
|
-
primary_key,
|
63
|
+
"SQL",
|
64
|
+
primary_key || false,
|
69
65
|
primary_key_value,
|
70
66
|
nil,
|
71
67
|
binds)
|
@@ -88,7 +84,7 @@ module ActiveRecord
|
|
88
84
|
|
89
85
|
@klass.connection.update(
|
90
86
|
um,
|
91
|
-
|
87
|
+
"SQL",
|
92
88
|
bvs,
|
93
89
|
)
|
94
90
|
end
|
@@ -247,7 +243,6 @@ module ActiveRecord
|
|
247
243
|
# Please see further details in the
|
248
244
|
# {Active Record Query Interface guide}[http://guides.rubyonrails.org/active_record_querying.html#running-explain].
|
249
245
|
def explain
|
250
|
-
#TODO: Fix for binds.
|
251
246
|
exec_explain(collecting_queries_for_explain { exec_queries })
|
252
247
|
end
|
253
248
|
|
@@ -279,12 +274,7 @@ module ActiveRecord
|
|
279
274
|
def empty?
|
280
275
|
return @records.empty? if loaded?
|
281
276
|
|
282
|
-
|
283
|
-
true
|
284
|
-
else
|
285
|
-
c = count(:all)
|
286
|
-
c.respond_to?(:zero?) ? c.zero? : c.empty?
|
287
|
-
end
|
277
|
+
limit_value == 0 || !exists?
|
288
278
|
end
|
289
279
|
|
290
280
|
# Returns true if there are no records.
|
@@ -347,7 +337,7 @@ module ActiveRecord
|
|
347
337
|
# Please check unscoped if you want to remove all previous scopes (including
|
348
338
|
# the default_scope) during the execution of a block.
|
349
339
|
def scoping
|
350
|
-
previous, klass.current_scope = klass.current_scope
|
340
|
+
previous, klass.current_scope = klass.current_scope, self
|
351
341
|
yield
|
352
342
|
ensure
|
353
343
|
klass.current_scope = previous
|
@@ -383,7 +373,7 @@ module ActiveRecord
|
|
383
373
|
stmt.set Arel.sql(@klass.send(:sanitize_sql_for_assignment, updates))
|
384
374
|
stmt.table(table)
|
385
375
|
|
386
|
-
if
|
376
|
+
if has_join_values?
|
387
377
|
@klass.connection.join_to_update(stmt, arel, arel_attribute(primary_key))
|
388
378
|
else
|
389
379
|
stmt.key = arel_attribute(primary_key)
|
@@ -392,7 +382,7 @@ module ActiveRecord
|
|
392
382
|
stmt.wheres = arel.constraints
|
393
383
|
end
|
394
384
|
|
395
|
-
@klass.connection.update stmt,
|
385
|
+
@klass.connection.update stmt, "SQL", bound_attributes
|
396
386
|
end
|
397
387
|
|
398
388
|
# Updates an object (or multiple objects) and saves it to the database, if validations pass.
|
@@ -428,8 +418,7 @@ module ActiveRecord
|
|
428
418
|
records.each { |record| record.update(attributes) }
|
429
419
|
else
|
430
420
|
if ActiveRecord::Base === id
|
431
|
-
|
432
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
421
|
+
raise ArgumentError, <<-MSG.squish
|
433
422
|
You are passing an instance of ActiveRecord::Base to `update`.
|
434
423
|
Please pass the id of the object by calling `.id`.
|
435
424
|
MSG
|
@@ -456,16 +445,8 @@ module ActiveRecord
|
|
456
445
|
# ==== Examples
|
457
446
|
#
|
458
447
|
# Person.where(age: 0..18).destroy_all
|
459
|
-
def destroy_all
|
460
|
-
|
461
|
-
ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
|
462
|
-
Passing conditions to destroy_all is deprecated and will be removed in Rails 5.1.
|
463
|
-
To achieve the same use where(conditions).destroy_all.
|
464
|
-
MESSAGE
|
465
|
-
where(conditions).destroy_all
|
466
|
-
else
|
467
|
-
records.each(&:destroy).tap { reset }
|
468
|
-
end
|
448
|
+
def destroy_all
|
449
|
+
records.each(&:destroy).tap { reset }
|
469
450
|
end
|
470
451
|
|
471
452
|
# Destroy an object (or multiple objects) that has the given id. The object is instantiated first,
|
@@ -513,41 +494,28 @@ module ActiveRecord
|
|
513
494
|
#
|
514
495
|
# Post.limit(100).delete_all
|
515
496
|
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support limit
|
516
|
-
def delete_all
|
517
|
-
invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
send("#{method}_value")
|
522
|
-
elsif CLAUSE_METHODS.include?(method)
|
523
|
-
send("#{method}_clause").any?
|
524
|
-
end
|
525
|
-
}
|
497
|
+
def delete_all
|
498
|
+
invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
|
499
|
+
value = get_value(method)
|
500
|
+
SINGLE_VALUE_METHODS.include?(method) ? value : value.any?
|
501
|
+
end
|
526
502
|
if invalid_methods.any?
|
527
503
|
raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
|
528
504
|
end
|
529
505
|
|
530
|
-
|
531
|
-
|
532
|
-
Passing conditions to delete_all is deprecated and will be removed in Rails 5.1.
|
533
|
-
To achieve the same use where(conditions).delete_all.
|
534
|
-
MESSAGE
|
535
|
-
where(conditions).delete_all
|
536
|
-
else
|
537
|
-
stmt = Arel::DeleteManager.new
|
538
|
-
stmt.from(table)
|
506
|
+
stmt = Arel::DeleteManager.new
|
507
|
+
stmt.from(table)
|
539
508
|
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
509
|
+
if has_join_values?
|
510
|
+
@klass.connection.join_to_delete(stmt, arel, arel_attribute(primary_key))
|
511
|
+
else
|
512
|
+
stmt.wheres = arel.constraints
|
513
|
+
end
|
545
514
|
|
546
|
-
|
515
|
+
affected = @klass.connection.delete(stmt, "SQL", bound_attributes)
|
547
516
|
|
548
|
-
|
549
|
-
|
550
|
-
end
|
517
|
+
reset
|
518
|
+
affected
|
551
519
|
end
|
552
520
|
|
553
521
|
# Deletes the row with a primary key matching the +id+ argument, using a
|
@@ -605,19 +573,16 @@ module ActiveRecord
|
|
605
573
|
# # => SELECT "users".* FROM "users" WHERE "users"."name" = 'Oscar'
|
606
574
|
def to_sql
|
607
575
|
@to_sql ||= begin
|
608
|
-
relation
|
609
|
-
connection = klass.connection
|
610
|
-
visitor = connection.visitor
|
576
|
+
relation = self
|
611
577
|
|
612
578
|
if eager_loading?
|
613
579
|
find_with_associations { |rel| relation = rel }
|
614
580
|
end
|
615
581
|
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
collect.substitute_binds(binds).join
|
582
|
+
conn = klass.connection
|
583
|
+
conn.unprepared_statement {
|
584
|
+
conn.to_sql(relation.arel, relation.bound_attributes)
|
585
|
+
}
|
621
586
|
end
|
622
587
|
end
|
623
588
|
|
@@ -648,15 +613,6 @@ module ActiveRecord
|
|
648
613
|
includes_values & joins_values
|
649
614
|
end
|
650
615
|
|
651
|
-
# {#uniq}[rdoc-ref:QueryMethods#uniq] and
|
652
|
-
# {#uniq!}[rdoc-ref:QueryMethods#uniq!] are silently deprecated.
|
653
|
-
# #uniq_value delegates to #distinct_value to maintain backwards compatibility.
|
654
|
-
# Use #distinct_value instead.
|
655
|
-
def uniq_value
|
656
|
-
distinct_value
|
657
|
-
end
|
658
|
-
deprecate uniq_value: :distinct_value
|
659
|
-
|
660
616
|
# Compares two relations for equality.
|
661
617
|
def ==(other)
|
662
618
|
case other
|
@@ -670,7 +626,7 @@ module ActiveRecord
|
|
670
626
|
end
|
671
627
|
|
672
628
|
def pretty_print(q)
|
673
|
-
q.pp(
|
629
|
+
q.pp(records)
|
674
630
|
end
|
675
631
|
|
676
632
|
# Returns true if relation is blank.
|
@@ -679,20 +635,16 @@ module ActiveRecord
|
|
679
635
|
end
|
680
636
|
|
681
637
|
def values
|
682
|
-
|
638
|
+
@values.dup
|
683
639
|
end
|
684
640
|
|
685
641
|
def inspect
|
686
642
|
entries = records.take([limit_value, 11].compact.min).map!(&:inspect)
|
687
|
-
entries[10] =
|
643
|
+
entries[10] = "..." if entries.size == 11
|
688
644
|
|
689
645
|
"#<#{self.class.name} [#{entries.join(', ')}]>"
|
690
646
|
end
|
691
647
|
|
692
|
-
def empty_scope? # :nodoc:
|
693
|
-
@values == klass.unscoped.values
|
694
|
-
end
|
695
|
-
|
696
648
|
protected
|
697
649
|
|
698
650
|
def load_records(records)
|
@@ -702,48 +654,53 @@ module ActiveRecord
|
|
702
654
|
|
703
655
|
private
|
704
656
|
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
preload = preload_values
|
709
|
-
preload += includes_values unless eager_loading?
|
710
|
-
preloader = build_preloader
|
711
|
-
preload.each do |associations|
|
712
|
-
preloader.preload @records, associations
|
657
|
+
def has_join_values?
|
658
|
+
joins_values.any? || left_outer_joins_values.any?
|
713
659
|
end
|
714
660
|
|
715
|
-
|
661
|
+
def exec_queries(&block)
|
662
|
+
@records = eager_loading? ? find_with_associations.freeze : @klass.find_by_sql(arel, bound_attributes, &block).freeze
|
716
663
|
|
717
|
-
|
718
|
-
|
719
|
-
|
664
|
+
preload = preload_values
|
665
|
+
preload += includes_values unless eager_loading?
|
666
|
+
preloader = nil
|
667
|
+
preload.each do |associations|
|
668
|
+
preloader ||= build_preloader
|
669
|
+
preloader.preload @records, associations
|
670
|
+
end
|
720
671
|
|
721
|
-
|
722
|
-
ActiveRecord::Associations::Preloader.new
|
723
|
-
end
|
672
|
+
@records.each(&:readonly!) if readonly_value
|
724
673
|
|
725
|
-
|
726
|
-
|
727
|
-
if join.is_a?(Arel::Nodes::StringJoin)
|
728
|
-
tables_in_string(join.left)
|
729
|
-
else
|
730
|
-
[join.left.table_name, join.left.table_alias]
|
731
|
-
end
|
674
|
+
@loaded = true
|
675
|
+
@records
|
732
676
|
end
|
733
677
|
|
734
|
-
|
678
|
+
def build_preloader
|
679
|
+
ActiveRecord::Associations::Preloader.new
|
680
|
+
end
|
735
681
|
|
736
|
-
|
737
|
-
|
682
|
+
def references_eager_loaded_tables?
|
683
|
+
joined_tables = arel.join_sources.map do |join|
|
684
|
+
if join.is_a?(Arel::Nodes::StringJoin)
|
685
|
+
tables_in_string(join.left)
|
686
|
+
else
|
687
|
+
[join.left.table_name, join.left.table_alias]
|
688
|
+
end
|
689
|
+
end
|
738
690
|
|
739
|
-
|
740
|
-
end
|
691
|
+
joined_tables += [table.name, table.table_alias]
|
741
692
|
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
693
|
+
# always convert table names to downcase as in Oracle quoted table names are in uppercase
|
694
|
+
joined_tables = joined_tables.flatten.compact.map(&:downcase).uniq
|
695
|
+
|
696
|
+
(references_values - joined_tables).any?
|
697
|
+
end
|
698
|
+
|
699
|
+
def tables_in_string(string)
|
700
|
+
return [] if string.blank?
|
701
|
+
# always convert table names to downcase as in Oracle quoted table names are in uppercase
|
702
|
+
# ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
|
703
|
+
string.scan(/([a-zA-Z_][.\w]+).?\./).flatten.map(&:downcase).uniq - ["raw_sql_"]
|
704
|
+
end
|
748
705
|
end
|
749
706
|
end
|