activerecord 5.1.7 → 5.2.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 +221 -900
- data/README.rdoc +3 -3
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +10 -3
- data/lib/active_record/aggregations.rb +2 -0
- data/lib/active_record/association_relation.rb +2 -0
- data/lib/active_record/associations.rb +13 -42
- data/lib/active_record/associations/alias_tracker.rb +17 -17
- data/lib/active_record/associations/association.rb +11 -22
- data/lib/active_record/associations/association_scope.rb +32 -44
- data/lib/active_record/associations/belongs_to_association.rb +6 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -1
- data/lib/active_record/associations/builder/association.rb +2 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -12
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +41 -33
- data/lib/active_record/associations/collection_proxy.rb +11 -14
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +4 -2
- data/lib/active_record/associations/has_many_through_association.rb +4 -2
- data/lib/active_record/associations/has_one_association.rb +3 -1
- data/lib/active_record/associations/has_one_through_association.rb +3 -1
- data/lib/active_record/associations/join_dependency.rb +22 -40
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/preloader/association.rb +42 -58
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/singular_association.rb +14 -10
- data/lib/active_record/associations/through_association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +2 -0
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +47 -7
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +25 -214
- data/lib/active_record/attribute_methods/primary_key.rb +7 -6
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +8 -2
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +21 -9
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +5 -11
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +6 -8
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +2 -0
- data/lib/active_record/collection_cache_key.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +120 -28
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -33
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +13 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +40 -2
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +103 -63
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -90
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +75 -138
- data/lib/active_record/connection_adapters/column.rb +3 -1
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +3 -1
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -6
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +91 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +11 -7
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +79 -65
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +47 -82
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -0
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +19 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -89
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +27 -57
- data/lib/active_record/counter_cache.rb +15 -12
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +15 -13
- data/lib/active_record/errors.rb +54 -21
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +40 -24
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +6 -5
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +31 -20
- data/lib/active_record/locking/pessimistic.rb +10 -7
- data/lib/active_record/log_subscriber.rb +2 -0
- data/lib/active_record/migration.rb +47 -21
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +20 -2
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +29 -38
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +184 -40
- data/lib/active_record/query_cache.rb +17 -12
- data/lib/active_record/querying.rb +3 -1
- data/lib/active_record/railtie.rb +54 -1
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +41 -28
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +100 -182
- data/lib/active_record/relation.rb +61 -193
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +40 -23
- data/lib/active_record/relation/delegation.rb +10 -27
- data/lib/active_record/relation/finder_methods.rb +53 -49
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +22 -19
- data/lib/active_record/relation/predicate_builder.rb +42 -79
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +9 -2
- data/lib/active_record/relation/query_methods.rb +80 -69
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -0
- data/lib/active_record/relation/where_clause.rb +50 -67
- data/lib/active_record/relation/where_clause_factory.rb +4 -46
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +15 -9
- data/lib/active_record/schema.rb +3 -1
- data/lib/active_record/schema_dumper.rb +24 -23
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +6 -7
- data/lib/active_record/scoping/named.rb +15 -7
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +22 -12
- data/lib/active_record/store.rb +2 -0
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +3 -1
- data/lib/active_record/tasks/database_tasks.rb +23 -12
- data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
- data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +5 -12
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +2 -4
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +2 -0
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +36 -6
- data/lib/active_record/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +25 -38
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -122
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/attribute_set/builder.rb +0 -126
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -37
data/README.rdoc
CHANGED
@@ -26,7 +26,7 @@ The Product class is automatically mapped to the table named "products",
|
|
26
26
|
which might look like this:
|
27
27
|
|
28
28
|
CREATE TABLE products (
|
29
|
-
id
|
29
|
+
id bigint NOT NULL auto_increment,
|
30
30
|
name varchar(255),
|
31
31
|
PRIMARY KEY (id)
|
32
32
|
);
|
@@ -162,7 +162,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
162
162
|
== Philosophy
|
163
163
|
|
164
164
|
Active Record is an implementation of the object-relational mapping (ORM)
|
165
|
-
pattern[
|
165
|
+
pattern[https://www.martinfowler.com/eaaCatalog/activeRecord.html] by the same
|
166
166
|
name described by Martin Fowler:
|
167
167
|
|
168
168
|
"An object that wraps a row in a database table or view,
|
@@ -199,7 +199,7 @@ Source code can be downloaded as part of the Rails project on GitHub:
|
|
199
199
|
|
200
200
|
Active Record is released under the MIT license:
|
201
201
|
|
202
|
-
*
|
202
|
+
* https://opensource.org/licenses/MIT
|
203
203
|
|
204
204
|
|
205
205
|
== Support
|
data/examples/performance.rb
CHANGED
data/examples/simple.rb
CHANGED
data/lib/active_record.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#--
|
2
4
|
# Copyright (c) 2004-2017 David Heinemeier Hansson
|
3
5
|
#
|
@@ -25,14 +27,14 @@ require "active_support"
|
|
25
27
|
require "active_support/rails"
|
26
28
|
require "active_model"
|
27
29
|
require "arel"
|
30
|
+
require "yaml"
|
28
31
|
|
29
32
|
require "active_record/version"
|
30
|
-
require "
|
33
|
+
require "active_model/attribute_set"
|
31
34
|
|
32
35
|
module ActiveRecord
|
33
36
|
extend ActiveSupport::Autoload
|
34
37
|
|
35
|
-
autoload :Attribute
|
36
38
|
autoload :Base
|
37
39
|
autoload :Callbacks
|
38
40
|
autoload :Core
|
@@ -102,6 +104,7 @@ module ActiveRecord
|
|
102
104
|
|
103
105
|
autoload :Result
|
104
106
|
autoload :TableMetadata
|
107
|
+
autoload :Type
|
105
108
|
end
|
106
109
|
|
107
110
|
module Coders
|
@@ -177,5 +180,9 @@ ActiveSupport.on_load(:active_record) do
|
|
177
180
|
end
|
178
181
|
|
179
182
|
ActiveSupport.on_load(:i18n) do
|
180
|
-
I18n.load_path << File.
|
183
|
+
I18n.load_path << File.expand_path("active_record/locale/en.yml", __dir__)
|
181
184
|
end
|
185
|
+
|
186
|
+
YAML.load_tags["!ruby/object:ActiveRecord::AttributeSet"] = "ActiveModel::AttributeSet"
|
187
|
+
YAML.load_tags["!ruby/object:ActiveRecord::Attribute::FromDatabase"] = "ActiveModel::Attribute::FromDatabase"
|
188
|
+
YAML.load_tags["!ruby/object:ActiveRecord::LazyAttributeHash"] = "ActiveModel::LazyAttributeHash"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/enumerable"
|
2
4
|
require "active_support/core_ext/string/conversions"
|
3
5
|
require "active_support/core_ext/module/remove_method"
|
@@ -138,26 +140,6 @@ module ActiveRecord
|
|
138
140
|
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
|
139
141
|
end
|
140
142
|
|
141
|
-
class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc:
|
142
|
-
def initialize(owner = nil, reflection = nil)
|
143
|
-
if owner && reflection
|
144
|
-
super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.")
|
145
|
-
else
|
146
|
-
super("Cannot associate new records.")
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc:
|
152
|
-
def initialize(owner = nil, reflection = nil)
|
153
|
-
if owner && reflection
|
154
|
-
super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.")
|
155
|
-
else
|
156
|
-
super("Cannot dissociate new records.")
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
143
|
class ThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc:
|
162
144
|
def initialize(owner = nil, reflection = nil)
|
163
145
|
if owner && reflection
|
@@ -187,16 +169,6 @@ module ActiveRecord
|
|
187
169
|
end
|
188
170
|
end
|
189
171
|
|
190
|
-
class ReadOnlyAssociation < ActiveRecordError #:nodoc:
|
191
|
-
def initialize(reflection = nil)
|
192
|
-
if reflection
|
193
|
-
super("Cannot add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.")
|
194
|
-
else
|
195
|
-
super("Read-only reflection error.")
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
172
|
# This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
|
201
173
|
# (has_many, has_one) when there is at least 1 child associated instance.
|
202
174
|
# ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
|
@@ -481,14 +453,14 @@ module ActiveRecord
|
|
481
453
|
# The tables for these classes could look something like:
|
482
454
|
#
|
483
455
|
# CREATE TABLE users (
|
484
|
-
# id
|
485
|
-
# account_id
|
456
|
+
# id bigint NOT NULL auto_increment,
|
457
|
+
# account_id bigint default NULL,
|
486
458
|
# name varchar default NULL,
|
487
459
|
# PRIMARY KEY (id)
|
488
460
|
# )
|
489
461
|
#
|
490
462
|
# CREATE TABLE accounts (
|
491
|
-
# id
|
463
|
+
# id bigint NOT NULL auto_increment,
|
492
464
|
# name varchar default NULL,
|
493
465
|
# PRIMARY KEY (id)
|
494
466
|
# )
|
@@ -555,9 +527,8 @@ module ActiveRecord
|
|
555
527
|
# has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
|
556
528
|
# end
|
557
529
|
#
|
558
|
-
# Note: Joining, eager loading and preloading of these associations is not
|
530
|
+
# Note: Joining, eager loading and preloading of these associations is not possible.
|
559
531
|
# These operations happen before instance creation and the scope will be called with a +nil+ argument.
|
560
|
-
# This can lead to unexpected behavior and is deprecated.
|
561
532
|
#
|
562
533
|
# == Association callbacks
|
563
534
|
#
|
@@ -848,7 +819,7 @@ module ActiveRecord
|
|
848
819
|
# project.milestones # fetches milestones from the database
|
849
820
|
# project.milestones.size # uses the milestone cache
|
850
821
|
# project.milestones.empty? # uses the milestone cache
|
851
|
-
# project.milestones
|
822
|
+
# project.milestones.reload.size # fetches milestones from the database
|
852
823
|
# project.milestones # uses the milestone cache
|
853
824
|
#
|
854
825
|
# == Eager loading of associations
|
@@ -1189,7 +1160,7 @@ module ActiveRecord
|
|
1189
1160
|
# +collection+ is a placeholder for the symbol passed as the +name+ argument, so
|
1190
1161
|
# <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
|
1191
1162
|
#
|
1192
|
-
# [collection
|
1163
|
+
# [collection]
|
1193
1164
|
# Returns a Relation of all the associated objects.
|
1194
1165
|
# An empty Relation is returned if none are found.
|
1195
1166
|
# [collection<<(object, ...)]
|
@@ -1398,7 +1369,7 @@ module ActiveRecord
|
|
1398
1369
|
# has_many :tags, as: :taggable
|
1399
1370
|
# has_many :reports, -> { readonly }
|
1400
1371
|
# has_many :subscribers, through: :subscriptions, source: :user
|
1401
|
-
def has_many(name, scope = nil, options
|
1372
|
+
def has_many(name, scope = nil, **options, &extension)
|
1402
1373
|
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
|
1403
1374
|
Reflection.add_reflection self, name, reflection
|
1404
1375
|
end
|
@@ -1532,7 +1503,7 @@ module ActiveRecord
|
|
1532
1503
|
# has_one :club, through: :membership
|
1533
1504
|
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
1534
1505
|
# has_one :credit_card, required: true
|
1535
|
-
def has_one(name, scope = nil, options
|
1506
|
+
def has_one(name, scope = nil, **options)
|
1536
1507
|
reflection = Builder::HasOne.build(self, name, scope, options)
|
1537
1508
|
Reflection.add_reflection self, name, reflection
|
1538
1509
|
end
|
@@ -1676,7 +1647,7 @@ module ActiveRecord
|
|
1676
1647
|
# belongs_to :company, touch: :employees_last_updated_at
|
1677
1648
|
# belongs_to :user, optional: true
|
1678
1649
|
# belongs_to :account, default: -> { company.account }
|
1679
|
-
def belongs_to(name, scope = nil, options
|
1650
|
+
def belongs_to(name, scope = nil, **options)
|
1680
1651
|
reflection = Builder::BelongsTo.build(self, name, scope, options)
|
1681
1652
|
Reflection.add_reflection self, name, reflection
|
1682
1653
|
end
|
@@ -1846,7 +1817,7 @@ module ActiveRecord
|
|
1846
1817
|
|
1847
1818
|
builder = Builder::HasAndBelongsToMany.new name, self, options
|
1848
1819
|
|
1849
|
-
join_model =
|
1820
|
+
join_model = builder.through_model
|
1850
1821
|
|
1851
1822
|
const_set join_model.name, join_model
|
1852
1823
|
private_constant join_model.name
|
@@ -1875,7 +1846,7 @@ module ActiveRecord
|
|
1875
1846
|
hm_options[k] = options[k] if options.key? k
|
1876
1847
|
end
|
1877
1848
|
|
1878
|
-
|
1849
|
+
has_many name, scope, hm_options, &extension
|
1879
1850
|
_reflections[name.to_s].parent_reflection = habtm_reflection
|
1880
1851
|
end
|
1881
1852
|
end
|
@@ -1,41 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/string/conversions"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Associations
|
5
7
|
# Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
|
6
8
|
class AliasTracker # :nodoc:
|
7
|
-
|
8
|
-
|
9
|
-
def self.create(connection, initial_table)
|
10
|
-
aliases = Hash.new(0)
|
11
|
-
aliases[initial_table] = 1
|
12
|
-
new(connection, aliases)
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.create_with_joins(connection, initial_table, joins)
|
9
|
+
def self.create(connection, initial_table, joins)
|
16
10
|
if joins.empty?
|
17
|
-
|
11
|
+
aliases = Hash.new(0)
|
18
12
|
else
|
19
13
|
aliases = Hash.new { |h, k|
|
20
14
|
h[k] = initial_count_for(connection, k, joins)
|
21
15
|
}
|
22
|
-
aliases[initial_table] = 1
|
23
|
-
new(connection, aliases)
|
24
16
|
end
|
17
|
+
aliases[initial_table] = 1
|
18
|
+
new(connection, aliases)
|
25
19
|
end
|
26
20
|
|
27
21
|
def self.initial_count_for(connection, name, table_joins)
|
28
|
-
|
29
|
-
quoted_name = connection.quote_table_name(name).downcase
|
22
|
+
quoted_name = nil
|
30
23
|
|
31
24
|
counts = table_joins.map do |join|
|
32
25
|
if join.is_a?(Arel::Nodes::StringJoin)
|
26
|
+
# quoted_name should be case ignored as some database adapters (Oracle) return quoted name in uppercase
|
27
|
+
quoted_name ||= connection.quote_table_name(name)
|
28
|
+
|
33
29
|
# Table names + table aliases
|
34
|
-
join.left.
|
35
|
-
/
|
30
|
+
join.left.scan(
|
31
|
+
/JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
|
36
32
|
).size
|
37
33
|
elsif join.respond_to? :left
|
38
|
-
join.left.
|
34
|
+
join.left.name == name ? 1 : 0
|
35
|
+
elsif join.is_a?(Hash)
|
36
|
+
join.fetch(name, 0)
|
39
37
|
else
|
40
38
|
# this branch is reached by two tests:
|
41
39
|
#
|
@@ -79,6 +77,8 @@ module ActiveRecord
|
|
79
77
|
end
|
80
78
|
end
|
81
79
|
|
80
|
+
attr_reader :aliases
|
81
|
+
|
82
82
|
private
|
83
83
|
|
84
84
|
def truncate(name)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/array/wrap"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -30,14 +32,6 @@ module ActiveRecord
|
|
30
32
|
reset_scope
|
31
33
|
end
|
32
34
|
|
33
|
-
# Returns the name of the table of the associated class:
|
34
|
-
#
|
35
|
-
# post.comments.aliased_table_name # => "comments"
|
36
|
-
#
|
37
|
-
def aliased_table_name
|
38
|
-
klass.table_name
|
39
|
-
end
|
40
|
-
|
41
35
|
# Resets the \loaded flag to +false+ and sets the \target to +nil+.
|
42
36
|
def reset
|
43
37
|
@loaded = false
|
@@ -94,7 +88,7 @@ module ActiveRecord
|
|
94
88
|
# actually gets built.
|
95
89
|
def association_scope
|
96
90
|
if klass
|
97
|
-
@association_scope ||= AssociationScope.scope(self
|
91
|
+
@association_scope ||= AssociationScope.scope(self)
|
98
92
|
end
|
99
93
|
end
|
100
94
|
|
@@ -136,8 +130,8 @@ module ActiveRecord
|
|
136
130
|
def extensions
|
137
131
|
extensions = klass.default_extensions | reflection.extensions
|
138
132
|
|
139
|
-
if
|
140
|
-
extensions |= klass.unscoped
|
133
|
+
if reflection.scope
|
134
|
+
extensions |= reflection.scope_for(klass.unscoped, owner).extensions
|
141
135
|
end
|
142
136
|
|
143
137
|
extensions
|
@@ -162,14 +156,6 @@ module ActiveRecord
|
|
162
156
|
reset
|
163
157
|
end
|
164
158
|
|
165
|
-
def interpolate(sql, record = nil)
|
166
|
-
if sql.respond_to?(:to_proc)
|
167
|
-
owner.instance_exec(record, &sql)
|
168
|
-
else
|
169
|
-
sql
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
159
|
# We can't dump @reflection since it contains the scope proc
|
174
160
|
def marshal_dump
|
175
161
|
ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
|
@@ -187,8 +173,8 @@ module ActiveRecord
|
|
187
173
|
skip_assign = [reflection.foreign_key, reflection.type].compact
|
188
174
|
assigned_keys = record.changed_attribute_names_to_save
|
189
175
|
assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
|
190
|
-
attributes =
|
191
|
-
record.
|
176
|
+
attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
|
177
|
+
record.send(:_assign_attributes, attributes) if attributes.any?
|
192
178
|
set_inverse_instance(record)
|
193
179
|
end
|
194
180
|
|
@@ -201,6 +187,9 @@ module ActiveRecord
|
|
201
187
|
end
|
202
188
|
|
203
189
|
private
|
190
|
+
def scope_for_create
|
191
|
+
scope.scope_for_create
|
192
|
+
end
|
204
193
|
|
205
194
|
def find_target?
|
206
195
|
!loaded? && (!owner.new_record? || foreign_key_present?) && klass
|
@@ -284,7 +273,7 @@ module ActiveRecord
|
|
284
273
|
end
|
285
274
|
|
286
275
|
# Returns true if statement cache should be skipped on the association reader.
|
287
|
-
def skip_statement_cache?
|
276
|
+
def skip_statement_cache?(scope)
|
288
277
|
reflection.has_scope? ||
|
289
278
|
scope.eager_loading? ||
|
290
279
|
klass.scope_attributes? ||
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
class AssociationScope #:nodoc:
|
4
|
-
def self.scope(association
|
5
|
-
INSTANCE.scope(association
|
6
|
+
def self.scope(association)
|
7
|
+
INSTANCE.scope(association)
|
6
8
|
end
|
7
9
|
|
8
10
|
def self.create(&block)
|
@@ -16,20 +18,15 @@ module ActiveRecord
|
|
16
18
|
|
17
19
|
INSTANCE = create
|
18
20
|
|
19
|
-
def scope(association
|
21
|
+
def scope(association)
|
20
22
|
klass = association.klass
|
21
23
|
reflection = association.reflection
|
22
24
|
scope = klass.unscoped
|
23
25
|
owner = association.owner
|
24
|
-
|
25
|
-
chain_head, chain_tail = get_chain(reflection, association, alias_tracker)
|
26
|
+
chain = get_chain(reflection, association, scope.alias_tracker)
|
26
27
|
|
27
28
|
scope.extending! reflection.extensions
|
28
|
-
add_constraints(scope, owner,
|
29
|
-
end
|
30
|
-
|
31
|
-
def join_type
|
32
|
-
Arel::Nodes::InnerJoin
|
29
|
+
add_constraints(scope, owner, chain)
|
33
30
|
end
|
34
31
|
|
35
32
|
def self.get_bind_values(owner, chain)
|
@@ -57,14 +54,15 @@ module ActiveRecord
|
|
57
54
|
|
58
55
|
private
|
59
56
|
def join(table, constraint)
|
60
|
-
table.create_join(table, table.create_on(constraint)
|
57
|
+
table.create_join(table, table.create_on(constraint))
|
61
58
|
end
|
62
59
|
|
63
|
-
def last_chain_scope(scope,
|
60
|
+
def last_chain_scope(scope, reflection, owner)
|
64
61
|
join_keys = reflection.join_keys
|
65
62
|
key = join_keys.key
|
66
63
|
foreign_key = join_keys.foreign_key
|
67
64
|
|
65
|
+
table = reflection.aliased_table
|
68
66
|
value = transform_value(owner[foreign_key])
|
69
67
|
scope = apply_scope(scope, table, key, value)
|
70
68
|
|
@@ -80,11 +78,13 @@ module ActiveRecord
|
|
80
78
|
value_transformation.call(value)
|
81
79
|
end
|
82
80
|
|
83
|
-
def next_chain_scope(scope,
|
81
|
+
def next_chain_scope(scope, reflection, next_reflection)
|
84
82
|
join_keys = reflection.join_keys
|
85
83
|
key = join_keys.key
|
86
84
|
foreign_key = join_keys.foreign_key
|
87
85
|
|
86
|
+
table = reflection.aliased_table
|
87
|
+
foreign_table = next_reflection.aliased_table
|
88
88
|
constraint = table[key].eq(foreign_table[foreign_key])
|
89
89
|
|
90
90
|
if reflection.type
|
@@ -96,12 +96,11 @@ module ActiveRecord
|
|
96
96
|
end
|
97
97
|
|
98
98
|
class ReflectionProxy < SimpleDelegator # :nodoc:
|
99
|
-
|
100
|
-
attr_reader :alias_name
|
99
|
+
attr_reader :aliased_table
|
101
100
|
|
102
|
-
def initialize(reflection,
|
101
|
+
def initialize(reflection, aliased_table)
|
103
102
|
super(reflection)
|
104
|
-
@
|
103
|
+
@aliased_table = aliased_table
|
105
104
|
end
|
106
105
|
|
107
106
|
def all_includes; nil; end
|
@@ -109,42 +108,33 @@ module ActiveRecord
|
|
109
108
|
|
110
109
|
def get_chain(reflection, association, tracker)
|
111
110
|
name = reflection.name
|
112
|
-
|
113
|
-
previous_reflection = runtime_reflection
|
111
|
+
chain = [Reflection::RuntimeReflection.new(reflection, association)]
|
114
112
|
reflection.chain.drop(1).each do |refl|
|
115
|
-
|
113
|
+
aliased_table = tracker.aliased_table_for(
|
116
114
|
refl.table_name,
|
117
115
|
refl.alias_candidate(name),
|
118
116
|
refl.klass.type_caster
|
119
117
|
)
|
120
|
-
|
121
|
-
previous_reflection.next = proxy
|
122
|
-
previous_reflection = proxy
|
118
|
+
chain << ReflectionProxy.new(refl, aliased_table)
|
123
119
|
end
|
124
|
-
|
120
|
+
chain
|
125
121
|
end
|
126
122
|
|
127
|
-
def add_constraints(scope, owner,
|
128
|
-
|
129
|
-
table = owner_reflection.alias_name
|
130
|
-
scope = last_chain_scope(scope, table, owner_reflection, owner)
|
131
|
-
|
132
|
-
reflection = chain_head
|
133
|
-
while reflection
|
134
|
-
table = reflection.alias_name
|
135
|
-
next_reflection = reflection.next
|
123
|
+
def add_constraints(scope, owner, chain)
|
124
|
+
scope = last_chain_scope(scope, chain.last, owner)
|
136
125
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
end
|
126
|
+
chain.each_cons(2) do |reflection, next_reflection|
|
127
|
+
scope = next_chain_scope(scope, reflection, next_reflection)
|
128
|
+
end
|
141
129
|
|
130
|
+
chain_head = chain.first
|
131
|
+
chain.reverse_each do |reflection|
|
142
132
|
# Exclude the scope of the association itself, because that
|
143
133
|
# was already merged in the #scope method.
|
144
134
|
reflection.constraints.each do |scope_chain_item|
|
145
|
-
item = eval_scope(reflection
|
135
|
+
item = eval_scope(reflection, scope_chain_item, owner)
|
146
136
|
|
147
|
-
if scope_chain_item ==
|
137
|
+
if scope_chain_item == chain_head.scope
|
148
138
|
scope.merge! item.except(:where, :includes)
|
149
139
|
end
|
150
140
|
|
@@ -156,8 +146,6 @@ module ActiveRecord
|
|
156
146
|
scope.where_clause += item.where_clause
|
157
147
|
scope.order_values |= item.order_values
|
158
148
|
end
|
159
|
-
|
160
|
-
reflection = next_reflection
|
161
149
|
end
|
162
150
|
|
163
151
|
scope
|
@@ -171,9 +159,9 @@ module ActiveRecord
|
|
171
159
|
end
|
172
160
|
end
|
173
161
|
|
174
|
-
def eval_scope(
|
175
|
-
|
176
|
-
|
162
|
+
def eval_scope(reflection, scope, owner)
|
163
|
+
relation = reflection.build_scope(reflection.aliased_table)
|
164
|
+
relation.instance_exec(owner, &scope) || relation
|
177
165
|
end
|
178
166
|
end
|
179
167
|
end
|