activerecord 5.1.5 → 5.2.1
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 +4 -4
- data/CHANGELOG.md +450 -699
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +4 -2
- data/lib/active_record/associations/alias_tracker.rb +19 -27
- data/lib/active_record/associations/association.rb +33 -37
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +14 -5
- 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 +52 -41
- data/lib/active_record/associations/collection_proxy.rb +12 -15
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +3 -1
- data/lib/active_record/associations/has_many_through_association.rb +8 -19
- data/lib/active_record/associations/has_one_association.rb +12 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency/join_association.rb +22 -67
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
- data/lib/active_record/associations/join_dependency.rb +48 -93
- data/lib/active_record/associations/preloader/association.rb +45 -61
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/associations.rb +40 -63
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- 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 +9 -3
- 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/attribute_methods.rb +65 -24
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +16 -14
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +12 -6
- 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 +11 -7
- 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 +157 -29
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -32
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +149 -78
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +92 -165
- 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 +47 -2
- 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 -10
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -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/array.rb +6 -0
- 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.rb +23 -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 +8 -2
- 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/oid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +248 -112
- 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 +57 -73
- data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
- 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 +20 -1
- 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 +75 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +79 -92
- 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 +39 -60
- data/lib/active_record/counter_cache.rb +20 -15
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +17 -13
- data/lib/active_record/errors.rb +42 -3
- 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 +67 -60
- data/lib/active_record/gem_version.rb +4 -2
- data/lib/active_record/inheritance.rb +49 -19
- 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 +30 -42
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +43 -0
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +40 -2
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/model_schema.rb +19 -24
- 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 +196 -48
- data/lib/active_record/query_cache.rb +12 -14
- data/lib/active_record/querying.rb +3 -1
- data/lib/active_record/railtie.rb +61 -3
- 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 +46 -36
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +110 -192
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/calculations.rb +31 -9
- data/lib/active_record/relation/delegation.rb +15 -27
- data/lib/active_record/relation/finder_methods.rb +71 -76
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +47 -20
- 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 +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +55 -79
- data/lib/active_record/relation/query_attribute.rb +26 -2
- data/lib/active_record/relation/query_methods.rb +95 -91
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -1
- data/lib/active_record/relation/where_clause.rb +65 -68
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/relation.rb +106 -219
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +129 -121
- data/lib/active_record/schema.rb +4 -2
- data/lib/active_record/schema_dumper.rb +36 -26
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping/default.rb +6 -7
- data/lib/active_record/scoping/named.rb +21 -7
- data/lib/active_record/scoping.rb +9 -8
- 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 +3 -1
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +12 -3
- data/lib/active_record/tasks/database_tasks.rb +25 -14
- 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 +13 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +32 -27
- data/lib/active_record/translation.rb +2 -0
- 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 +6 -0
- 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.rb +4 -1
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.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/validations.rb +2 -0
- data/lib/active_record/version.rb +2 -0
- data/lib/active_record.rb +11 -4
- 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/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/migration.rb +2 -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
- data/lib/rails/generators/active_record.rb +3 -1
- metadata +23 -36
- 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/user_provided_default.rb +0 -30
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute_mutation_tracker.rb +0 -114
- data/lib/active_record/attribute_set/builder.rb +0 -124
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/attribute_set.rb +0 -113
- 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
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class Relation
|
3
5
|
class WhereClauseFactory # :nodoc:
|
@@ -9,69 +11,24 @@ module ActiveRecord
|
|
9
11
|
def build(opts, other)
|
10
12
|
case opts
|
11
13
|
when String, Array
|
12
|
-
parts = [klass.
|
14
|
+
parts = [klass.sanitize_sql(other.empty? ? opts : ([opts] + other))]
|
13
15
|
when Hash
|
14
16
|
attributes = predicate_builder.resolve_column_aliases(opts)
|
15
|
-
attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes)
|
16
17
|
attributes.stringify_keys!
|
17
18
|
|
18
|
-
|
19
|
-
parts, binds = build_for_case_sensitive(attributes, options)
|
20
|
-
else
|
21
|
-
attributes, binds = predicate_builder.create_binds(attributes)
|
22
|
-
parts = predicate_builder.build_from_hash(attributes)
|
23
|
-
end
|
19
|
+
parts = predicate_builder.build_from_hash(attributes)
|
24
20
|
when Arel::Nodes::Node
|
25
21
|
parts = [opts]
|
26
22
|
else
|
27
23
|
raise ArgumentError, "Unsupported argument type: #{opts} (#{opts.class})"
|
28
24
|
end
|
29
25
|
|
30
|
-
WhereClause.new(parts
|
26
|
+
WhereClause.new(parts)
|
31
27
|
end
|
32
28
|
|
33
|
-
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
34
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
35
29
|
protected
|
36
30
|
|
37
31
|
attr_reader :klass, :predicate_builder
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def perform_case_sensitive?(options)
|
42
|
-
options && options.key?(:case_sensitive)
|
43
|
-
end
|
44
|
-
|
45
|
-
def build_for_case_sensitive(attributes, options)
|
46
|
-
parts, binds = [], []
|
47
|
-
table = klass.arel_table
|
48
|
-
|
49
|
-
attributes.each do |attribute, value|
|
50
|
-
if reflection = klass._reflect_on_association(attribute)
|
51
|
-
attribute = reflection.foreign_key.to_s
|
52
|
-
value = value[reflection.klass.primary_key] unless value.nil?
|
53
|
-
end
|
54
|
-
|
55
|
-
if value.nil?
|
56
|
-
parts << table[attribute].eq(value)
|
57
|
-
else
|
58
|
-
column = klass.column_for_attribute(attribute)
|
59
|
-
|
60
|
-
binds << predicate_builder.send(:build_bind_param, attribute, value)
|
61
|
-
value = Arel::Nodes::BindParam.new
|
62
|
-
|
63
|
-
predicate = if options[:case_sensitive]
|
64
|
-
klass.connection.case_sensitive_comparison(table, attribute, column, value)
|
65
|
-
else
|
66
|
-
klass.connection.case_insensitive_comparison(table, attribute, column, value)
|
67
|
-
end
|
68
|
-
|
69
|
-
parts << predicate
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
[parts, binds]
|
74
|
-
end
|
75
32
|
end
|
76
33
|
end
|
77
34
|
end
|
@@ -1,14 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record \Relation
|
3
5
|
class Relation
|
4
6
|
MULTI_VALUE_METHODS = [:includes, :eager_load, :preload, :select, :group,
|
5
|
-
:order, :joins, :
|
7
|
+
:order, :joins, :left_outer_joins, :references,
|
6
8
|
:extending, :unscope]
|
7
9
|
|
8
10
|
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering,
|
9
|
-
:reverse_order, :distinct, :create_with]
|
11
|
+
:reverse_order, :distinct, :create_with, :skip_query_cache]
|
10
12
|
CLAUSE_METHODS = [:where, :having, :from]
|
11
|
-
INVALID_METHODS_FOR_DELETE_ALL = [:
|
13
|
+
INVALID_METHODS_FOR_DELETE_ALL = [:distinct, :group, :having]
|
12
14
|
|
13
15
|
VALUE_METHODS = MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS + CLAUSE_METHODS
|
14
16
|
|
@@ -18,14 +20,16 @@ module ActiveRecord
|
|
18
20
|
attr_reader :table, :klass, :loaded, :predicate_builder
|
19
21
|
alias :model :klass
|
20
22
|
alias :loaded? :loaded
|
23
|
+
alias :locked? :lock_value
|
21
24
|
|
22
|
-
def initialize(klass, table, predicate_builder, values
|
25
|
+
def initialize(klass, table: klass.arel_table, predicate_builder: klass.predicate_builder, values: {})
|
23
26
|
@klass = klass
|
24
27
|
@table = table
|
25
28
|
@values = values
|
26
29
|
@offsets = {}
|
27
30
|
@loaded = false
|
28
31
|
@predicate_builder = predicate_builder
|
32
|
+
@delegate_to_klass = false
|
29
33
|
end
|
30
34
|
|
31
35
|
def initialize_copy(other)
|
@@ -33,74 +37,6 @@ module ActiveRecord
|
|
33
37
|
reset
|
34
38
|
end
|
35
39
|
|
36
|
-
def insert(values) # :nodoc:
|
37
|
-
primary_key_value = nil
|
38
|
-
|
39
|
-
if primary_key && Hash === values
|
40
|
-
primary_key_value = values[values.keys.find { |k|
|
41
|
-
k.name == primary_key
|
42
|
-
}]
|
43
|
-
|
44
|
-
if !primary_key_value && klass.prefetch_primary_key?
|
45
|
-
primary_key_value = klass.next_sequence_value
|
46
|
-
values[arel_attribute(klass.primary_key)] = primary_key_value
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
im = arel.create_insert
|
51
|
-
im.into @table
|
52
|
-
|
53
|
-
substitutes, binds = substitute_values values
|
54
|
-
|
55
|
-
if values.empty? # empty insert
|
56
|
-
im.values = Arel.sql(connection.empty_insert_statement_value)
|
57
|
-
else
|
58
|
-
im.insert substitutes
|
59
|
-
end
|
60
|
-
|
61
|
-
@klass.connection.insert(
|
62
|
-
im,
|
63
|
-
"SQL",
|
64
|
-
primary_key || false,
|
65
|
-
primary_key_value,
|
66
|
-
nil,
|
67
|
-
binds)
|
68
|
-
end
|
69
|
-
|
70
|
-
def _update_record(values, id, id_was) # :nodoc:
|
71
|
-
substitutes, binds = substitute_values values
|
72
|
-
|
73
|
-
scope = @klass.unscoped
|
74
|
-
|
75
|
-
if @klass.finder_needs_type_condition?
|
76
|
-
scope.unscope!(where: @klass.inheritance_column)
|
77
|
-
end
|
78
|
-
|
79
|
-
relation = scope.where(@klass.primary_key => (id_was || id))
|
80
|
-
bvs = binds + relation.bound_attributes
|
81
|
-
um = relation
|
82
|
-
.arel
|
83
|
-
.compile_update(substitutes, @klass.primary_key)
|
84
|
-
|
85
|
-
@klass.connection.update(
|
86
|
-
um,
|
87
|
-
"SQL",
|
88
|
-
bvs,
|
89
|
-
)
|
90
|
-
end
|
91
|
-
|
92
|
-
def substitute_values(values) # :nodoc:
|
93
|
-
binds = []
|
94
|
-
substitutes = []
|
95
|
-
|
96
|
-
values.each do |arel_attr, value|
|
97
|
-
binds.push QueryAttribute.new(arel_attr.name, value, klass.type_for_attribute(arel_attr.name))
|
98
|
-
substitutes.push [arel_attr, Arel::Nodes::BindParam.new]
|
99
|
-
end
|
100
|
-
|
101
|
-
[substitutes, binds]
|
102
|
-
end
|
103
|
-
|
104
40
|
def arel_attribute(name) # :nodoc:
|
105
41
|
klass.arel_attribute(name, table)
|
106
42
|
end
|
@@ -117,8 +53,8 @@ module ActiveRecord
|
|
117
53
|
#
|
118
54
|
# user = users.new { |user| user.name = 'Oscar' }
|
119
55
|
# user.name # => Oscar
|
120
|
-
def new(
|
121
|
-
scoping {
|
56
|
+
def new(attributes = nil, &block)
|
57
|
+
scoping { klass.new(scope_for_create(attributes), &block) }
|
122
58
|
end
|
123
59
|
|
124
60
|
alias build new
|
@@ -142,8 +78,12 @@ module ActiveRecord
|
|
142
78
|
#
|
143
79
|
# users.create(name: nil) # validation on name
|
144
80
|
# # => #<User id: nil, name: nil, ...>
|
145
|
-
def create(
|
146
|
-
|
81
|
+
def create(attributes = nil, &block)
|
82
|
+
if attributes.is_a?(Array)
|
83
|
+
attributes.collect { |attr| create(attr, &block) }
|
84
|
+
else
|
85
|
+
scoping { klass.create(scope_for_create(attributes), &block) }
|
86
|
+
end
|
147
87
|
end
|
148
88
|
|
149
89
|
# Similar to #create, but calls
|
@@ -152,8 +92,12 @@ module ActiveRecord
|
|
152
92
|
#
|
153
93
|
# Expects arguments in the same format as
|
154
94
|
# {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!].
|
155
|
-
def create!(
|
156
|
-
|
95
|
+
def create!(attributes = nil, &block)
|
96
|
+
if attributes.is_a?(Array)
|
97
|
+
attributes.collect { |attr| create!(attr, &block) }
|
98
|
+
else
|
99
|
+
scoping { klass.create!(scope_for_create(attributes), &block) }
|
100
|
+
end
|
157
101
|
end
|
158
102
|
|
159
103
|
def first_or_create(attributes = nil, &block) # :nodoc:
|
@@ -247,9 +191,10 @@ module ActiveRecord
|
|
247
191
|
end
|
248
192
|
|
249
193
|
# Converts relation objects to Array.
|
250
|
-
def
|
194
|
+
def to_ary
|
251
195
|
records.dup
|
252
196
|
end
|
197
|
+
alias to_a to_ary
|
253
198
|
|
254
199
|
def records # :nodoc:
|
255
200
|
load
|
@@ -332,10 +277,17 @@ module ActiveRecord
|
|
332
277
|
# Please check unscoped if you want to remove all previous scopes (including
|
333
278
|
# the default_scope) during the execution of a block.
|
334
279
|
def scoping
|
335
|
-
previous, klass.current_scope = klass.current_scope(true), self
|
280
|
+
previous, klass.current_scope = klass.current_scope(true), self unless @delegate_to_klass
|
336
281
|
yield
|
337
282
|
ensure
|
338
|
-
klass.current_scope = previous
|
283
|
+
klass.current_scope = previous unless @delegate_to_klass
|
284
|
+
end
|
285
|
+
|
286
|
+
def _exec_scope(*args, &block) # :nodoc:
|
287
|
+
@delegate_to_klass = true
|
288
|
+
instance_exec(*args, &block) || self
|
289
|
+
ensure
|
290
|
+
@delegate_to_klass = false
|
339
291
|
end
|
340
292
|
|
341
293
|
# Updates all records in the current relation with details given. This method constructs a single SQL UPDATE
|
@@ -363,12 +315,17 @@ module ActiveRecord
|
|
363
315
|
def update_all(updates)
|
364
316
|
raise ArgumentError, "Empty list of attributes to change" if updates.blank?
|
365
317
|
|
318
|
+
if eager_loading?
|
319
|
+
relation = apply_join_dependency
|
320
|
+
return relation.update_all(updates)
|
321
|
+
end
|
322
|
+
|
366
323
|
stmt = Arel::UpdateManager.new
|
367
324
|
|
368
|
-
stmt.set Arel.sql(@klass.
|
325
|
+
stmt.set Arel.sql(@klass.sanitize_sql_for_assignment(updates))
|
369
326
|
stmt.table(table)
|
370
327
|
|
371
|
-
if has_join_values?
|
328
|
+
if has_join_values? || offset_value
|
372
329
|
@klass.connection.join_to_update(stmt, arel, arel_attribute(primary_key))
|
373
330
|
else
|
374
331
|
stmt.key = arel_attribute(primary_key)
|
@@ -377,51 +334,7 @@ module ActiveRecord
|
|
377
334
|
stmt.wheres = arel.constraints
|
378
335
|
end
|
379
336
|
|
380
|
-
@klass.connection.update stmt, "
|
381
|
-
end
|
382
|
-
|
383
|
-
# Updates an object (or multiple objects) and saves it to the database, if validations pass.
|
384
|
-
# The resulting object is returned whether the object was saved successfully to the database or not.
|
385
|
-
#
|
386
|
-
# ==== Parameters
|
387
|
-
#
|
388
|
-
# * +id+ - This should be the id or an array of ids to be updated.
|
389
|
-
# * +attributes+ - This should be a hash of attributes or an array of hashes.
|
390
|
-
#
|
391
|
-
# ==== Examples
|
392
|
-
#
|
393
|
-
# # Updates one record
|
394
|
-
# Person.update(15, user_name: 'Samuel', group: 'expert')
|
395
|
-
#
|
396
|
-
# # Updates multiple records
|
397
|
-
# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
|
398
|
-
# Person.update(people.keys, people.values)
|
399
|
-
#
|
400
|
-
# # Updates multiple records from the result of a relation
|
401
|
-
# people = Person.where(group: 'expert')
|
402
|
-
# people.update(group: 'masters')
|
403
|
-
#
|
404
|
-
# Note: Updating a large number of records will run an
|
405
|
-
# UPDATE query for each record, which may cause a performance
|
406
|
-
# issue. So if it is not needed to run callbacks for each update, it is
|
407
|
-
# preferred to use #update_all for updating all records using
|
408
|
-
# a single query.
|
409
|
-
def update(id = :all, attributes)
|
410
|
-
if id.is_a?(Array)
|
411
|
-
id.map.with_index { |one_id, idx| update(one_id, attributes[idx]) }
|
412
|
-
elsif id == :all
|
413
|
-
records.each { |record| record.update(attributes) }
|
414
|
-
else
|
415
|
-
if ActiveRecord::Base === id
|
416
|
-
raise ArgumentError, <<-MSG.squish
|
417
|
-
You are passing an instance of ActiveRecord::Base to `update`.
|
418
|
-
Please pass the id of the object by calling `.id`.
|
419
|
-
MSG
|
420
|
-
end
|
421
|
-
object = find(id)
|
422
|
-
object.update(attributes)
|
423
|
-
object
|
424
|
-
end
|
337
|
+
@klass.connection.update stmt, "#{@klass} Update All"
|
425
338
|
end
|
426
339
|
|
427
340
|
# Destroys the records by instantiating each
|
@@ -444,33 +357,6 @@ module ActiveRecord
|
|
444
357
|
records.each(&:destroy).tap { reset }
|
445
358
|
end
|
446
359
|
|
447
|
-
# Destroy an object (or multiple objects) that has the given id. The object is instantiated first,
|
448
|
-
# therefore all callbacks and filters are fired off before the object is deleted. This method is
|
449
|
-
# less efficient than #delete but allows cleanup methods and other actions to be run.
|
450
|
-
#
|
451
|
-
# This essentially finds the object (or multiple objects) with the given id, creates a new object
|
452
|
-
# from the attributes, and then calls destroy on it.
|
453
|
-
#
|
454
|
-
# ==== Parameters
|
455
|
-
#
|
456
|
-
# * +id+ - Can be either an Integer or an Array of Integers.
|
457
|
-
#
|
458
|
-
# ==== Examples
|
459
|
-
#
|
460
|
-
# # Destroy a single object
|
461
|
-
# Todo.destroy(1)
|
462
|
-
#
|
463
|
-
# # Destroy multiple objects
|
464
|
-
# todos = [1,2,3]
|
465
|
-
# Todo.destroy(todos)
|
466
|
-
def destroy(id)
|
467
|
-
if id.is_a?(Array)
|
468
|
-
id.map { |one_id| destroy(one_id) }
|
469
|
-
else
|
470
|
-
find(id).destroy
|
471
|
-
end
|
472
|
-
end
|
473
|
-
|
474
360
|
# Deletes the records without instantiating the records
|
475
361
|
# first, and hence not calling the {#destroy}[rdoc-ref:Persistence#destroy]
|
476
362
|
# method nor invoking callbacks.
|
@@ -487,8 +373,8 @@ module ActiveRecord
|
|
487
373
|
#
|
488
374
|
# If an invalid method is supplied, #delete_all raises an ActiveRecordError:
|
489
375
|
#
|
490
|
-
# Post.
|
491
|
-
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support
|
376
|
+
# Post.distinct.delete_all
|
377
|
+
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support distinct
|
492
378
|
def delete_all
|
493
379
|
invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
|
494
380
|
value = get_value(method)
|
@@ -498,44 +384,26 @@ module ActiveRecord
|
|
498
384
|
raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
|
499
385
|
end
|
500
386
|
|
387
|
+
if eager_loading?
|
388
|
+
relation = apply_join_dependency
|
389
|
+
return relation.delete_all
|
390
|
+
end
|
391
|
+
|
501
392
|
stmt = Arel::DeleteManager.new
|
502
393
|
stmt.from(table)
|
503
394
|
|
504
|
-
if has_join_values?
|
395
|
+
if has_join_values? || has_limit_or_offset?
|
505
396
|
@klass.connection.join_to_delete(stmt, arel, arel_attribute(primary_key))
|
506
397
|
else
|
507
398
|
stmt.wheres = arel.constraints
|
508
399
|
end
|
509
400
|
|
510
|
-
affected = @klass.connection.delete(stmt, "
|
401
|
+
affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
|
511
402
|
|
512
403
|
reset
|
513
404
|
affected
|
514
405
|
end
|
515
406
|
|
516
|
-
# Deletes the row with a primary key matching the +id+ argument, using a
|
517
|
-
# SQL +DELETE+ statement, and returns the number of rows deleted. Active
|
518
|
-
# Record objects are not instantiated, so the object's callbacks are not
|
519
|
-
# executed, including any <tt>:dependent</tt> association options.
|
520
|
-
#
|
521
|
-
# You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
|
522
|
-
#
|
523
|
-
# Note: Although it is often much faster than the alternative,
|
524
|
-
# #destroy, skipping callbacks might bypass business logic in
|
525
|
-
# your application that ensures referential integrity or performs other
|
526
|
-
# essential jobs.
|
527
|
-
#
|
528
|
-
# ==== Examples
|
529
|
-
#
|
530
|
-
# # Delete a single row
|
531
|
-
# Todo.delete(1)
|
532
|
-
#
|
533
|
-
# # Delete multiple rows
|
534
|
-
# Todo.delete([2,3,4])
|
535
|
-
def delete(id_or_array)
|
536
|
-
where(primary_key => id_or_array).delete_all
|
537
|
-
end
|
538
|
-
|
539
407
|
# Causes the records to be loaded from the database if they have not
|
540
408
|
# been loaded already. You can use this if for some reason you need
|
541
409
|
# to explicitly load some records before actually using them. The
|
@@ -555,8 +423,8 @@ module ActiveRecord
|
|
555
423
|
end
|
556
424
|
|
557
425
|
def reset
|
558
|
-
@
|
559
|
-
@
|
426
|
+
@delegate_to_klass = false
|
427
|
+
@to_sql = @arel = @loaded = @should_eager_load = nil
|
560
428
|
@records = [].freeze
|
561
429
|
@offsets = {}
|
562
430
|
self
|
@@ -568,29 +436,30 @@ module ActiveRecord
|
|
568
436
|
# # => SELECT "users".* FROM "users" WHERE "users"."name" = 'Oscar'
|
569
437
|
def to_sql
|
570
438
|
@to_sql ||= begin
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
end
|
439
|
+
if eager_loading?
|
440
|
+
apply_join_dependency do |relation, join_dependency|
|
441
|
+
relation = join_dependency.apply_column_aliases(relation)
|
442
|
+
relation.to_sql
|
443
|
+
end
|
444
|
+
else
|
445
|
+
conn = klass.connection
|
446
|
+
conn.unprepared_statement { conn.to_sql(arel) }
|
447
|
+
end
|
448
|
+
end
|
582
449
|
end
|
583
450
|
|
584
451
|
# Returns a hash of where conditions.
|
585
452
|
#
|
586
453
|
# User.where(name: 'Oscar').where_values_hash
|
587
454
|
# # => {name: "Oscar"}
|
588
|
-
def where_values_hash(relation_table_name = table_name)
|
455
|
+
def where_values_hash(relation_table_name = klass.table_name)
|
589
456
|
where_clause.to_h(relation_table_name)
|
590
457
|
end
|
591
458
|
|
592
|
-
def scope_for_create
|
593
|
-
|
459
|
+
def scope_for_create(attributes = nil)
|
460
|
+
scope = where_values_hash.merge!(create_with_value.stringify_keys)
|
461
|
+
scope.merge!(attributes) if attributes
|
462
|
+
scope
|
594
463
|
end
|
595
464
|
|
596
465
|
# Returns true if relation needs eager loading.
|
@@ -650,6 +519,11 @@ module ActiveRecord
|
|
650
519
|
limit_value || offset_value
|
651
520
|
end
|
652
521
|
|
522
|
+
def alias_tracker(joins = [], aliases = nil) # :nodoc:
|
523
|
+
joins += [aliases] if aliases
|
524
|
+
ActiveRecord::Associations::AliasTracker.create(connection, table.name, joins)
|
525
|
+
end
|
526
|
+
|
653
527
|
protected
|
654
528
|
|
655
529
|
def load_records(records)
|
@@ -664,32 +538,45 @@ module ActiveRecord
|
|
664
538
|
end
|
665
539
|
|
666
540
|
def exec_queries(&block)
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
541
|
+
skip_query_cache_if_necessary do
|
542
|
+
@records =
|
543
|
+
if eager_loading?
|
544
|
+
apply_join_dependency do |relation, join_dependency|
|
545
|
+
if ActiveRecord::NullRelation === relation
|
546
|
+
[]
|
547
|
+
else
|
548
|
+
relation = join_dependency.apply_column_aliases(relation)
|
549
|
+
rows = connection.select_all(relation.arel, "SQL")
|
550
|
+
join_dependency.instantiate(rows, &block)
|
551
|
+
end.freeze
|
552
|
+
end
|
553
|
+
else
|
554
|
+
klass.find_by_sql(arel, &block).freeze
|
676
555
|
end
|
677
|
-
|
678
|
-
|
556
|
+
|
557
|
+
preload = preload_values
|
558
|
+
preload += includes_values unless eager_loading?
|
559
|
+
preloader = nil
|
560
|
+
preload.each do |associations|
|
561
|
+
preloader ||= build_preloader
|
562
|
+
preloader.preload @records, associations
|
679
563
|
end
|
680
564
|
|
681
|
-
|
682
|
-
preload += includes_values unless eager_loading?
|
683
|
-
preloader = nil
|
684
|
-
preload.each do |associations|
|
685
|
-
preloader ||= build_preloader
|
686
|
-
preloader.preload @records, associations
|
687
|
-
end
|
565
|
+
@records.each(&:readonly!) if readonly_value
|
688
566
|
|
689
|
-
|
567
|
+
@loaded = true
|
568
|
+
@records
|
569
|
+
end
|
570
|
+
end
|
690
571
|
|
691
|
-
|
692
|
-
|
572
|
+
def skip_query_cache_if_necessary
|
573
|
+
if skip_query_cache_value
|
574
|
+
uncached do
|
575
|
+
yield
|
576
|
+
end
|
577
|
+
else
|
578
|
+
yield
|
579
|
+
end
|
693
580
|
end
|
694
581
|
|
695
582
|
def build_preloader
|
data/lib/active_record/result.rb
CHANGED