activerecord 5.1.0 → 5.2.3
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 +596 -450
- 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.rb +11 -4
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations.rb +77 -85
- data/lib/active_record/associations/alias_tracker.rb +23 -32
- data/lib/active_record/associations/association.rb +49 -35
- data/lib/active_record/associations/association_scope.rb +55 -55
- data/lib/active_record/associations/belongs_to_association.rb +30 -11
- 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 +21 -8
- 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 +66 -53
- data/lib/active_record/associations/collection_proxy.rb +30 -73
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +13 -2
- data/lib/active_record/associations/has_many_through_association.rb +37 -19
- data/lib/active_record/associations/has_one_association.rb +14 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency.rb +52 -96
- data/lib/active_record/associations/join_dependency/join_association.rb +22 -75
- 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/preloader.rb +17 -37
- data/lib/active_record/associations/preloader/association.rb +53 -92
- data/lib/active_record/associations/preloader/through_association.rb +72 -73
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +27 -12
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +33 -216
- data/lib/active_record/attribute_methods/primary_key.rb +10 -13
- 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 +22 -19
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +15 -13
- 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 +15 -11
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +120 -39
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +192 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +13 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -25
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +65 -7
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -87
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +86 -98
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +126 -189
- data/lib/active_record/connection_adapters/column.rb +4 -2
- 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 +45 -15
- 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 -23
- 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 +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +13 -1
- 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 -11
- 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/quoting.rb +22 -1
- 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 +258 -129
- 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 +75 -87
- 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 +24 -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 +90 -96
- 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 +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 +18 -13
- data/lib/active_record/errors.rb +60 -15
- 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 +10 -7
- data/lib/active_record/log_subscriber.rb +46 -4
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +81 -29
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +74 -58
- 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 +199 -54
- data/lib/active_record/query_cache.rb +8 -10
- data/lib/active_record/querying.rb +5 -3
- 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 +48 -38
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +137 -207
- data/lib/active_record/relation.rb +132 -207
- data/lib/active_record/relation/batches.rb +32 -17
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +66 -25
- data/lib/active_record/relation/delegation.rb +45 -29
- data/lib/active_record/relation/finder_methods.rb +76 -85
- 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.rb +60 -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 +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/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +135 -103
- 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 -67
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- 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.rb +12 -10
- data/lib/active_record/scoping/default.rb +10 -7
- data/lib/active_record/scoping/named.rb +40 -12
- 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 +38 -26
- data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
- 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.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 +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_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- 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 +24 -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.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -113
- data/lib/active_record/attribute_set.rb +0 -113
- 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/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 -33
@@ -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(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
|
@@ -269,8 +214,7 @@ module ActiveRecord
|
|
269
214
|
# Returns true if there are no records.
|
270
215
|
def empty?
|
271
216
|
return @records.empty? if loaded?
|
272
|
-
|
273
|
-
limit_value == 0 || !exists?
|
217
|
+
!exists?
|
274
218
|
end
|
275
219
|
|
276
220
|
# Returns true if there are no records.
|
@@ -333,10 +277,17 @@ module ActiveRecord
|
|
333
277
|
# Please check unscoped if you want to remove all previous scopes (including
|
334
278
|
# the default_scope) during the execution of a block.
|
335
279
|
def scoping
|
336
|
-
previous, klass.current_scope = klass.current_scope, self
|
280
|
+
previous, klass.current_scope = klass.current_scope(true), self unless @delegate_to_klass
|
337
281
|
yield
|
338
282
|
ensure
|
339
|
-
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
|
340
291
|
end
|
341
292
|
|
342
293
|
# Updates all records in the current relation with details given. This method constructs a single SQL UPDATE
|
@@ -364,12 +315,17 @@ module ActiveRecord
|
|
364
315
|
def update_all(updates)
|
365
316
|
raise ArgumentError, "Empty list of attributes to change" if updates.blank?
|
366
317
|
|
318
|
+
if eager_loading?
|
319
|
+
relation = apply_join_dependency
|
320
|
+
return relation.update_all(updates)
|
321
|
+
end
|
322
|
+
|
367
323
|
stmt = Arel::UpdateManager.new
|
368
324
|
|
369
|
-
stmt.set Arel.sql(@klass.
|
325
|
+
stmt.set Arel.sql(@klass.sanitize_sql_for_assignment(updates))
|
370
326
|
stmt.table(table)
|
371
327
|
|
372
|
-
if has_join_values?
|
328
|
+
if has_join_values? || offset_value
|
373
329
|
@klass.connection.join_to_update(stmt, arel, arel_attribute(primary_key))
|
374
330
|
else
|
375
331
|
stmt.key = arel_attribute(primary_key)
|
@@ -378,50 +334,14 @@ module ActiveRecord
|
|
378
334
|
stmt.wheres = arel.constraints
|
379
335
|
end
|
380
336
|
|
381
|
-
@klass.connection.update stmt, "
|
337
|
+
@klass.connection.update stmt, "#{@klass} Update All"
|
382
338
|
end
|
383
339
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
# ==== Parameters
|
388
|
-
#
|
389
|
-
# * +id+ - This should be the id or an array of ids to be updated.
|
390
|
-
# * +attributes+ - This should be a hash of attributes or an array of hashes.
|
391
|
-
#
|
392
|
-
# ==== Examples
|
393
|
-
#
|
394
|
-
# # Updates one record
|
395
|
-
# Person.update(15, user_name: 'Samuel', group: 'expert')
|
396
|
-
#
|
397
|
-
# # Updates multiple records
|
398
|
-
# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
|
399
|
-
# Person.update(people.keys, people.values)
|
400
|
-
#
|
401
|
-
# # Updates multiple records from the result of a relation
|
402
|
-
# people = Person.where(group: 'expert')
|
403
|
-
# people.update(group: 'masters')
|
404
|
-
#
|
405
|
-
# Note: Updating a large number of records will run an
|
406
|
-
# UPDATE query for each record, which may cause a performance
|
407
|
-
# issue. So if it is not needed to run callbacks for each update, it is
|
408
|
-
# preferred to use #update_all for updating all records using
|
409
|
-
# a single query.
|
410
|
-
def update(id = :all, attributes)
|
411
|
-
if id.is_a?(Array)
|
412
|
-
id.map.with_index { |one_id, idx| update(one_id, attributes[idx]) }
|
413
|
-
elsif id == :all
|
414
|
-
records.each { |record| record.update(attributes) }
|
340
|
+
def update(id = :all, attributes) # :nodoc:
|
341
|
+
if id == :all
|
342
|
+
each { |record| record.update(attributes) }
|
415
343
|
else
|
416
|
-
|
417
|
-
raise ArgumentError, <<-MSG.squish
|
418
|
-
You are passing an instance of ActiveRecord::Base to `update`.
|
419
|
-
Please pass the id of the object by calling `.id`.
|
420
|
-
MSG
|
421
|
-
end
|
422
|
-
object = find(id)
|
423
|
-
object.update(attributes)
|
424
|
-
object
|
344
|
+
klass.update(id, attributes)
|
425
345
|
end
|
426
346
|
end
|
427
347
|
|
@@ -445,33 +365,6 @@ module ActiveRecord
|
|
445
365
|
records.each(&:destroy).tap { reset }
|
446
366
|
end
|
447
367
|
|
448
|
-
# Destroy an object (or multiple objects) that has the given id. The object is instantiated first,
|
449
|
-
# therefore all callbacks and filters are fired off before the object is deleted. This method is
|
450
|
-
# less efficient than #delete but allows cleanup methods and other actions to be run.
|
451
|
-
#
|
452
|
-
# This essentially finds the object (or multiple objects) with the given id, creates a new object
|
453
|
-
# from the attributes, and then calls destroy on it.
|
454
|
-
#
|
455
|
-
# ==== Parameters
|
456
|
-
#
|
457
|
-
# * +id+ - Can be either an Integer or an Array of Integers.
|
458
|
-
#
|
459
|
-
# ==== Examples
|
460
|
-
#
|
461
|
-
# # Destroy a single object
|
462
|
-
# Todo.destroy(1)
|
463
|
-
#
|
464
|
-
# # Destroy multiple objects
|
465
|
-
# todos = [1,2,3]
|
466
|
-
# Todo.destroy(todos)
|
467
|
-
def destroy(id)
|
468
|
-
if id.is_a?(Array)
|
469
|
-
id.map { |one_id| destroy(one_id) }
|
470
|
-
else
|
471
|
-
find(id).destroy
|
472
|
-
end
|
473
|
-
end
|
474
|
-
|
475
368
|
# Deletes the records without instantiating the records
|
476
369
|
# first, and hence not calling the {#destroy}[rdoc-ref:Persistence#destroy]
|
477
370
|
# method nor invoking callbacks.
|
@@ -488,8 +381,8 @@ module ActiveRecord
|
|
488
381
|
#
|
489
382
|
# If an invalid method is supplied, #delete_all raises an ActiveRecordError:
|
490
383
|
#
|
491
|
-
# Post.
|
492
|
-
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support
|
384
|
+
# Post.distinct.delete_all
|
385
|
+
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support distinct
|
493
386
|
def delete_all
|
494
387
|
invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
|
495
388
|
value = get_value(method)
|
@@ -499,44 +392,26 @@ module ActiveRecord
|
|
499
392
|
raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
|
500
393
|
end
|
501
394
|
|
395
|
+
if eager_loading?
|
396
|
+
relation = apply_join_dependency
|
397
|
+
return relation.delete_all
|
398
|
+
end
|
399
|
+
|
502
400
|
stmt = Arel::DeleteManager.new
|
503
401
|
stmt.from(table)
|
504
402
|
|
505
|
-
if has_join_values?
|
403
|
+
if has_join_values? || has_limit_or_offset?
|
506
404
|
@klass.connection.join_to_delete(stmt, arel, arel_attribute(primary_key))
|
507
405
|
else
|
508
406
|
stmt.wheres = arel.constraints
|
509
407
|
end
|
510
408
|
|
511
|
-
affected = @klass.connection.delete(stmt, "
|
409
|
+
affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
|
512
410
|
|
513
411
|
reset
|
514
412
|
affected
|
515
413
|
end
|
516
414
|
|
517
|
-
# Deletes the row with a primary key matching the +id+ argument, using a
|
518
|
-
# SQL +DELETE+ statement, and returns the number of rows deleted. Active
|
519
|
-
# Record objects are not instantiated, so the object's callbacks are not
|
520
|
-
# executed, including any <tt>:dependent</tt> association options.
|
521
|
-
#
|
522
|
-
# You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
|
523
|
-
#
|
524
|
-
# Note: Although it is often much faster than the alternative,
|
525
|
-
# #destroy, skipping callbacks might bypass business logic in
|
526
|
-
# your application that ensures referential integrity or performs other
|
527
|
-
# essential jobs.
|
528
|
-
#
|
529
|
-
# ==== Examples
|
530
|
-
#
|
531
|
-
# # Delete a single row
|
532
|
-
# Todo.delete(1)
|
533
|
-
#
|
534
|
-
# # Delete multiple rows
|
535
|
-
# Todo.delete([2,3,4])
|
536
|
-
def delete(id_or_array)
|
537
|
-
where(primary_key => id_or_array).delete_all
|
538
|
-
end
|
539
|
-
|
540
415
|
# Causes the records to be loaded from the database if they have not
|
541
416
|
# been loaded already. You can use this if for some reason you need
|
542
417
|
# to explicitly load some records before actually using them. The
|
@@ -556,8 +431,8 @@ module ActiveRecord
|
|
556
431
|
end
|
557
432
|
|
558
433
|
def reset
|
559
|
-
@
|
560
|
-
@
|
434
|
+
@delegate_to_klass = false
|
435
|
+
@to_sql = @arel = @loaded = @should_eager_load = nil
|
561
436
|
@records = [].freeze
|
562
437
|
@offsets = {}
|
563
438
|
self
|
@@ -569,29 +444,28 @@ module ActiveRecord
|
|
569
444
|
# # => SELECT "users".* FROM "users" WHERE "users"."name" = 'Oscar'
|
570
445
|
def to_sql
|
571
446
|
@to_sql ||= begin
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
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
|
583
457
|
end
|
584
458
|
|
585
459
|
# Returns a hash of where conditions.
|
586
460
|
#
|
587
461
|
# User.where(name: 'Oscar').where_values_hash
|
588
462
|
# # => {name: "Oscar"}
|
589
|
-
def where_values_hash(relation_table_name = table_name)
|
463
|
+
def where_values_hash(relation_table_name = klass.table_name)
|
590
464
|
where_clause.to_h(relation_table_name)
|
591
465
|
end
|
592
466
|
|
593
467
|
def scope_for_create
|
594
|
-
|
468
|
+
where_values_hash.merge!(create_with_value.stringify_keys)
|
595
469
|
end
|
596
470
|
|
597
471
|
# Returns true if relation needs eager loading.
|
@@ -643,6 +517,19 @@ module ActiveRecord
|
|
643
517
|
"#<#{self.class.name} [#{entries.join(', ')}]>"
|
644
518
|
end
|
645
519
|
|
520
|
+
def empty_scope? # :nodoc:
|
521
|
+
@values == klass.unscoped.values
|
522
|
+
end
|
523
|
+
|
524
|
+
def has_limit_or_offset? # :nodoc:
|
525
|
+
limit_value || offset_value
|
526
|
+
end
|
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
|
+
|
646
533
|
protected
|
647
534
|
|
648
535
|
def load_records(records)
|
@@ -657,20 +544,45 @@ module ActiveRecord
|
|
657
544
|
end
|
658
545
|
|
659
546
|
def exec_queries(&block)
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
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
|
561
|
+
end
|
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
|
569
|
+
end
|
669
570
|
|
670
|
-
|
571
|
+
@records.each(&:readonly!) if readonly_value
|
671
572
|
|
672
|
-
|
673
|
-
|
573
|
+
@loaded = true
|
574
|
+
@records
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
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
|
674
586
|
end
|
675
587
|
|
676
588
|
def build_preloader
|
@@ -700,5 +612,18 @@ module ActiveRecord
|
|
700
612
|
# ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
|
701
613
|
string.scan(/([a-zA-Z_][.\w]+).?\./).flatten.map(&:downcase).uniq - ["raw_sql_"]
|
702
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
|
703
628
|
end
|
704
629
|
end
|