activerecord 5.1.7 → 5.2.6
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 +583 -673
- 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 +7 -5
- data/lib/active_record/associations/alias_tracker.rb +19 -27
- data/lib/active_record/associations/association.rb +41 -37
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +27 -8
- 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 +12 -4
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- 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 +59 -47
- data/lib/active_record/associations/collection_proxy.rb +20 -49
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +12 -1
- data/lib/active_record/associations/has_many_through_association.rb +36 -30
- 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 +39 -63
- 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 +18 -38
- 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 +30 -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 +6 -5
- data/lib/active_record/autosave_association.rb +35 -19
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +8 -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 +12 -8
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +139 -41
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -31
- 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 +152 -81
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
- 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 +13 -2
- 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 +2 -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 +2 -0
- 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 +5 -3
- 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 +4 -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 +50 -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 +233 -111
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
- 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 +22 -0
- 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 +81 -94
- 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 +41 -61
- data/lib/active_record/counter_cache.rb +10 -3
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +18 -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 +14 -17
- 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 +47 -9
- 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 +16 -21
- 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 +167 -16
- data/lib/active_record/query_cache.rb +6 -8
- data/lib/active_record/querying.rb +4 -2
- data/lib/active_record/railtie.rb +62 -6
- 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 +108 -194
- 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 +45 -19
- data/lib/active_record/relation/delegation.rb +45 -27
- data/lib/active_record/relation/finder_methods.rb +75 -76
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +53 -23
- 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 +60 -79
- data/lib/active_record/relation/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +128 -99
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -2
- 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 +120 -214
- 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 +8 -9
- data/lib/active_record/scoping/named.rb +23 -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 +23 -13
- 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 +6 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +33 -28
- 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 +2 -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 +35 -5
- 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 -122
- 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/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,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, constraints) # :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(constraints)
|
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(values_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(values_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!(values_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,50 +334,14 @@ module ActiveRecord
|
|
377
334
|
stmt.wheres = arel.constraints
|
378
335
|
end
|
379
336
|
|
380
|
-
@klass.connection.update stmt, "
|
337
|
+
@klass.connection.update stmt, "#{@klass} Update All"
|
381
338
|
end
|
382
339
|
|
383
|
-
|
384
|
-
|
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) }
|
340
|
+
def update(id = :all, attributes) # :nodoc:
|
341
|
+
if id == :all
|
342
|
+
each { |record| record.update(attributes) }
|
414
343
|
else
|
415
|
-
|
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
|
344
|
+
klass.update(id, attributes)
|
424
345
|
end
|
425
346
|
end
|
426
347
|
|
@@ -444,33 +365,6 @@ module ActiveRecord
|
|
444
365
|
records.each(&:destroy).tap { reset }
|
445
366
|
end
|
446
367
|
|
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
368
|
# Deletes the records without instantiating the records
|
475
369
|
# first, and hence not calling the {#destroy}[rdoc-ref:Persistence#destroy]
|
476
370
|
# method nor invoking callbacks.
|
@@ -487,8 +381,8 @@ module ActiveRecord
|
|
487
381
|
#
|
488
382
|
# If an invalid method is supplied, #delete_all raises an ActiveRecordError:
|
489
383
|
#
|
490
|
-
# Post.
|
491
|
-
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support
|
384
|
+
# Post.distinct.delete_all
|
385
|
+
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support distinct
|
492
386
|
def delete_all
|
493
387
|
invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
|
494
388
|
value = get_value(method)
|
@@ -498,44 +392,26 @@ module ActiveRecord
|
|
498
392
|
raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
|
499
393
|
end
|
500
394
|
|
395
|
+
if eager_loading?
|
396
|
+
relation = apply_join_dependency
|
397
|
+
return relation.delete_all
|
398
|
+
end
|
399
|
+
|
501
400
|
stmt = Arel::DeleteManager.new
|
502
401
|
stmt.from(table)
|
503
402
|
|
504
|
-
if has_join_values?
|
403
|
+
if has_join_values? || has_limit_or_offset?
|
505
404
|
@klass.connection.join_to_delete(stmt, arel, arel_attribute(primary_key))
|
506
405
|
else
|
507
406
|
stmt.wheres = arel.constraints
|
508
407
|
end
|
509
408
|
|
510
|
-
affected = @klass.connection.delete(stmt, "
|
409
|
+
affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
|
511
410
|
|
512
411
|
reset
|
513
412
|
affected
|
514
413
|
end
|
515
414
|
|
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
415
|
# Causes the records to be loaded from the database if they have not
|
540
416
|
# been loaded already. You can use this if for some reason you need
|
541
417
|
# to explicitly load some records before actually using them. The
|
@@ -555,8 +431,8 @@ module ActiveRecord
|
|
555
431
|
end
|
556
432
|
|
557
433
|
def reset
|
558
|
-
@
|
559
|
-
@
|
434
|
+
@delegate_to_klass = false
|
435
|
+
@to_sql = @arel = @loaded = @should_eager_load = nil
|
560
436
|
@records = [].freeze
|
561
437
|
@offsets = {}
|
562
438
|
self
|
@@ -568,29 +444,28 @@ module ActiveRecord
|
|
568
444
|
# # => SELECT "users".* FROM "users" WHERE "users"."name" = 'Oscar'
|
569
445
|
def to_sql
|
570
446
|
@to_sql ||= begin
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
end
|
447
|
+
if eager_loading?
|
448
|
+
apply_join_dependency do |relation, join_dependency|
|
449
|
+
relation = join_dependency.apply_column_aliases(relation)
|
450
|
+
relation.to_sql
|
451
|
+
end
|
452
|
+
else
|
453
|
+
conn = klass.connection
|
454
|
+
conn.unprepared_statement { conn.to_sql(arel) }
|
455
|
+
end
|
456
|
+
end
|
582
457
|
end
|
583
458
|
|
584
459
|
# Returns a hash of where conditions.
|
585
460
|
#
|
586
461
|
# User.where(name: 'Oscar').where_values_hash
|
587
462
|
# # => {name: "Oscar"}
|
588
|
-
def where_values_hash(relation_table_name = table_name)
|
463
|
+
def where_values_hash(relation_table_name = klass.table_name)
|
589
464
|
where_clause.to_h(relation_table_name)
|
590
465
|
end
|
591
466
|
|
592
467
|
def scope_for_create
|
593
|
-
|
468
|
+
where_values_hash.merge!(create_with_value.stringify_keys)
|
594
469
|
end
|
595
470
|
|
596
471
|
# Returns true if relation needs eager loading.
|
@@ -650,6 +525,11 @@ module ActiveRecord
|
|
650
525
|
limit_value || offset_value
|
651
526
|
end
|
652
527
|
|
528
|
+
def alias_tracker(joins = [], aliases = nil) # :nodoc:
|
529
|
+
joins += [aliases] if aliases
|
530
|
+
ActiveRecord::Associations::AliasTracker.create(connection, table.name, joins)
|
531
|
+
end
|
532
|
+
|
653
533
|
protected
|
654
534
|
|
655
535
|
def load_records(records)
|
@@ -664,32 +544,45 @@ module ActiveRecord
|
|
664
544
|
end
|
665
545
|
|
666
546
|
def exec_queries(&block)
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
547
|
+
skip_query_cache_if_necessary do
|
548
|
+
@records =
|
549
|
+
if eager_loading?
|
550
|
+
apply_join_dependency do |relation, join_dependency|
|
551
|
+
if ActiveRecord::NullRelation === relation
|
552
|
+
[]
|
553
|
+
else
|
554
|
+
relation = join_dependency.apply_column_aliases(relation)
|
555
|
+
rows = connection.select_all(relation.arel, "SQL")
|
556
|
+
join_dependency.instantiate(rows, &block)
|
557
|
+
end.freeze
|
558
|
+
end
|
559
|
+
else
|
560
|
+
klass.find_by_sql(arel, &block).freeze
|
676
561
|
end
|
677
|
-
|
678
|
-
|
562
|
+
|
563
|
+
preload = preload_values
|
564
|
+
preload += includes_values unless eager_loading?
|
565
|
+
preloader = nil
|
566
|
+
preload.each do |associations|
|
567
|
+
preloader ||= build_preloader
|
568
|
+
preloader.preload @records, associations
|
679
569
|
end
|
680
570
|
|
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
|
571
|
+
@records.each(&:readonly!) if readonly_value
|
688
572
|
|
689
|
-
|
573
|
+
@loaded = true
|
574
|
+
@records
|
575
|
+
end
|
576
|
+
end
|
690
577
|
|
691
|
-
|
692
|
-
|
578
|
+
def skip_query_cache_if_necessary
|
579
|
+
if skip_query_cache_value
|
580
|
+
uncached do
|
581
|
+
yield
|
582
|
+
end
|
583
|
+
else
|
584
|
+
yield
|
585
|
+
end
|
693
586
|
end
|
694
587
|
|
695
588
|
def build_preloader
|
@@ -719,5 +612,18 @@ module ActiveRecord
|
|
719
612
|
# ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
|
720
613
|
string.scan(/([a-zA-Z_][.\w]+).?\./).flatten.map(&:downcase).uniq - ["raw_sql_"]
|
721
614
|
end
|
615
|
+
|
616
|
+
def values_for_create(attributes = nil)
|
617
|
+
result = attributes ? where_values_hash.merge!(attributes) : where_values_hash
|
618
|
+
|
619
|
+
# NOTE: if there are same keys in both create_with and result, create_with should be used.
|
620
|
+
# This is to make sure nested attributes don't get passed to the klass.new,
|
621
|
+
# while keeping the precedence of the duplicate keys in create_with.
|
622
|
+
create_with_value.stringify_keys.each do |k, v|
|
623
|
+
result[k] = v if result.key?(k)
|
624
|
+
end
|
625
|
+
|
626
|
+
result
|
627
|
+
end
|
722
628
|
end
|
723
629
|
end
|
data/lib/active_record/result.rb
CHANGED