activerecord 5.1.0 → 5.2.0.rc1
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 +410 -530
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- 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 +23 -32
- data/lib/active_record/associations/association.rb +20 -21
- data/lib/active_record/associations/association_scope.rb +49 -49
- data/lib/active_record/associations/belongs_to_association.rb +12 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +10 -6
- 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 +50 -41
- data/lib/active_record/associations/collection_proxy.rb +22 -39
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +4 -2
- data/lib/active_record/associations/has_many_through_association.rb +12 -18
- data/lib/active_record/associations/has_one_association.rb +5 -1
- data/lib/active_record/associations/has_one_through_association.rb +8 -7
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -64
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/join_dependency.rb +27 -44
- 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/preloader.rb +17 -37
- data/lib/active_record/associations/singular_association.rb +14 -10
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/associations.rb +68 -76
- data/lib/active_record/attribute_assignment.rb +2 -0
- 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 +24 -214
- 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 +8 -2
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +22 -19
- data/lib/active_record/attribute_methods.rb +48 -12
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +8 -11
- 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 +14 -10
- 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 +175 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -24
- 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 +58 -3
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +165 -85
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -97
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +118 -180
- 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 +2 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -17
- 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/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_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 +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 +2 -1
- 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 +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 +269 -126
- 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 +64 -85
- 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 +18 -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 +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +92 -95
- 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 +3 -2
- 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 +9 -9
- 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 +8 -6
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +46 -4
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +74 -22
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/migration.rb +181 -137
- data/lib/active_record/model_schema.rb +73 -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 +153 -18
- data/lib/active_record/query_cache.rb +17 -12
- data/lib/active_record/querying.rb +4 -2
- 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 +47 -37
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +131 -204
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/batches.rb +32 -17
- data/lib/active_record/relation/calculations.rb +58 -20
- data/lib/active_record/relation/delegation.rb +10 -29
- data/lib/active_record/relation/finder_methods.rb +74 -85
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +51 -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 +54 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +53 -78
- data/lib/active_record/relation/query_attribute.rb +9 -2
- data/lib/active_record/relation/query_methods.rb +101 -95
- 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 -67
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/relation.rb +99 -202
- 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 +10 -7
- data/lib/active_record/scoping/named.rb +38 -12
- data/lib/active_record/scoping.rb +12 -10
- 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 +37 -25
- 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 +5 -5
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type/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 +25 -37
- 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 -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/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 -33
@@ -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,8 +20,9 @@ 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
|
@@ -33,74 +36,6 @@ module ActiveRecord
|
|
33
36
|
reset
|
34
37
|
end
|
35
38
|
|
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
39
|
def arel_attribute(name) # :nodoc:
|
105
40
|
klass.arel_attribute(name, table)
|
106
41
|
end
|
@@ -117,8 +52,8 @@ module ActiveRecord
|
|
117
52
|
#
|
118
53
|
# user = users.new { |user| user.name = 'Oscar' }
|
119
54
|
# user.name # => Oscar
|
120
|
-
def new(
|
121
|
-
scoping {
|
55
|
+
def new(attributes = nil, &block)
|
56
|
+
scoping { klass.new(scope_for_create(attributes), &block) }
|
122
57
|
end
|
123
58
|
|
124
59
|
alias build new
|
@@ -142,8 +77,12 @@ module ActiveRecord
|
|
142
77
|
#
|
143
78
|
# users.create(name: nil) # validation on name
|
144
79
|
# # => #<User id: nil, name: nil, ...>
|
145
|
-
def create(
|
146
|
-
|
80
|
+
def create(attributes = nil, &block)
|
81
|
+
if attributes.is_a?(Array)
|
82
|
+
attributes.collect { |attr| create(attr, &block) }
|
83
|
+
else
|
84
|
+
scoping { klass.create(scope_for_create(attributes), &block) }
|
85
|
+
end
|
147
86
|
end
|
148
87
|
|
149
88
|
# Similar to #create, but calls
|
@@ -152,8 +91,12 @@ module ActiveRecord
|
|
152
91
|
#
|
153
92
|
# Expects arguments in the same format as
|
154
93
|
# {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!].
|
155
|
-
def create!(
|
156
|
-
|
94
|
+
def create!(attributes = nil, &block)
|
95
|
+
if attributes.is_a?(Array)
|
96
|
+
attributes.collect { |attr| create!(attr, &block) }
|
97
|
+
else
|
98
|
+
scoping { klass.create!(scope_for_create(attributes), &block) }
|
99
|
+
end
|
157
100
|
end
|
158
101
|
|
159
102
|
def first_or_create(attributes = nil, &block) # :nodoc:
|
@@ -247,9 +190,10 @@ module ActiveRecord
|
|
247
190
|
end
|
248
191
|
|
249
192
|
# Converts relation objects to Array.
|
250
|
-
def
|
193
|
+
def to_ary
|
251
194
|
records.dup
|
252
195
|
end
|
196
|
+
alias to_a to_ary
|
253
197
|
|
254
198
|
def records # :nodoc:
|
255
199
|
load
|
@@ -269,8 +213,7 @@ module ActiveRecord
|
|
269
213
|
# Returns true if there are no records.
|
270
214
|
def empty?
|
271
215
|
return @records.empty? if loaded?
|
272
|
-
|
273
|
-
limit_value == 0 || !exists?
|
216
|
+
!exists?
|
274
217
|
end
|
275
218
|
|
276
219
|
# Returns true if there are no records.
|
@@ -333,7 +276,7 @@ module ActiveRecord
|
|
333
276
|
# Please check unscoped if you want to remove all previous scopes (including
|
334
277
|
# the default_scope) during the execution of a block.
|
335
278
|
def scoping
|
336
|
-
previous, klass.current_scope = klass.current_scope, self
|
279
|
+
previous, klass.current_scope = klass.current_scope(true), self
|
337
280
|
yield
|
338
281
|
ensure
|
339
282
|
klass.current_scope = previous
|
@@ -364,12 +307,17 @@ module ActiveRecord
|
|
364
307
|
def update_all(updates)
|
365
308
|
raise ArgumentError, "Empty list of attributes to change" if updates.blank?
|
366
309
|
|
310
|
+
if eager_loading?
|
311
|
+
relation = apply_join_dependency
|
312
|
+
return relation.update_all(updates)
|
313
|
+
end
|
314
|
+
|
367
315
|
stmt = Arel::UpdateManager.new
|
368
316
|
|
369
|
-
stmt.set Arel.sql(@klass.
|
317
|
+
stmt.set Arel.sql(@klass.sanitize_sql_for_assignment(updates))
|
370
318
|
stmt.table(table)
|
371
319
|
|
372
|
-
if has_join_values?
|
320
|
+
if has_join_values? || offset_value
|
373
321
|
@klass.connection.join_to_update(stmt, arel, arel_attribute(primary_key))
|
374
322
|
else
|
375
323
|
stmt.key = arel_attribute(primary_key)
|
@@ -378,51 +326,7 @@ module ActiveRecord
|
|
378
326
|
stmt.wheres = arel.constraints
|
379
327
|
end
|
380
328
|
|
381
|
-
@klass.connection.update stmt, "
|
382
|
-
end
|
383
|
-
|
384
|
-
# Updates an object (or multiple objects) and saves it to the database, if validations pass.
|
385
|
-
# The resulting object is returned whether the object was saved successfully to the database or not.
|
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) }
|
415
|
-
else
|
416
|
-
if ActiveRecord::Base === id
|
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
|
425
|
-
end
|
329
|
+
@klass.connection.update stmt, "#{@klass} Update All"
|
426
330
|
end
|
427
331
|
|
428
332
|
# Destroys the records by instantiating each
|
@@ -445,33 +349,6 @@ module ActiveRecord
|
|
445
349
|
records.each(&:destroy).tap { reset }
|
446
350
|
end
|
447
351
|
|
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
352
|
# Deletes the records without instantiating the records
|
476
353
|
# first, and hence not calling the {#destroy}[rdoc-ref:Persistence#destroy]
|
477
354
|
# method nor invoking callbacks.
|
@@ -488,8 +365,8 @@ module ActiveRecord
|
|
488
365
|
#
|
489
366
|
# If an invalid method is supplied, #delete_all raises an ActiveRecordError:
|
490
367
|
#
|
491
|
-
# Post.
|
492
|
-
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support
|
368
|
+
# Post.distinct.delete_all
|
369
|
+
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support distinct
|
493
370
|
def delete_all
|
494
371
|
invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
|
495
372
|
value = get_value(method)
|
@@ -499,44 +376,26 @@ module ActiveRecord
|
|
499
376
|
raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
|
500
377
|
end
|
501
378
|
|
379
|
+
if eager_loading?
|
380
|
+
relation = apply_join_dependency
|
381
|
+
return relation.delete_all
|
382
|
+
end
|
383
|
+
|
502
384
|
stmt = Arel::DeleteManager.new
|
503
385
|
stmt.from(table)
|
504
386
|
|
505
|
-
if has_join_values?
|
387
|
+
if has_join_values? || has_limit_or_offset?
|
506
388
|
@klass.connection.join_to_delete(stmt, arel, arel_attribute(primary_key))
|
507
389
|
else
|
508
390
|
stmt.wheres = arel.constraints
|
509
391
|
end
|
510
392
|
|
511
|
-
affected = @klass.connection.delete(stmt, "
|
393
|
+
affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
|
512
394
|
|
513
395
|
reset
|
514
396
|
affected
|
515
397
|
end
|
516
398
|
|
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
399
|
# Causes the records to be loaded from the database if they have not
|
541
400
|
# been loaded already. You can use this if for some reason you need
|
542
401
|
# to explicitly load some records before actually using them. The
|
@@ -556,8 +415,7 @@ module ActiveRecord
|
|
556
415
|
end
|
557
416
|
|
558
417
|
def reset
|
559
|
-
@
|
560
|
-
@should_eager_load = @join_dependency = nil
|
418
|
+
@to_sql = @arel = @loaded = @should_eager_load = nil
|
561
419
|
@records = [].freeze
|
562
420
|
@offsets = {}
|
563
421
|
self
|
@@ -572,12 +430,12 @@ module ActiveRecord
|
|
572
430
|
relation = self
|
573
431
|
|
574
432
|
if eager_loading?
|
575
|
-
|
433
|
+
apply_join_dependency { |rel, _| relation = rel }
|
576
434
|
end
|
577
435
|
|
578
436
|
conn = klass.connection
|
579
437
|
conn.unprepared_statement {
|
580
|
-
conn.to_sql(relation.arel
|
438
|
+
conn.to_sql(relation.arel)
|
581
439
|
}
|
582
440
|
end
|
583
441
|
end
|
@@ -586,12 +444,14 @@ module ActiveRecord
|
|
586
444
|
#
|
587
445
|
# User.where(name: 'Oscar').where_values_hash
|
588
446
|
# # => {name: "Oscar"}
|
589
|
-
def where_values_hash(relation_table_name = table_name)
|
447
|
+
def where_values_hash(relation_table_name = klass.table_name)
|
590
448
|
where_clause.to_h(relation_table_name)
|
591
449
|
end
|
592
450
|
|
593
|
-
def scope_for_create
|
594
|
-
|
451
|
+
def scope_for_create(attributes = nil)
|
452
|
+
scope = where_values_hash.merge!(create_with_value.stringify_keys)
|
453
|
+
scope.merge!(attributes) if attributes
|
454
|
+
scope
|
595
455
|
end
|
596
456
|
|
597
457
|
# Returns true if relation needs eager loading.
|
@@ -643,6 +503,19 @@ module ActiveRecord
|
|
643
503
|
"#<#{self.class.name} [#{entries.join(', ')}]>"
|
644
504
|
end
|
645
505
|
|
506
|
+
def empty_scope? # :nodoc:
|
507
|
+
@values == klass.unscoped.values
|
508
|
+
end
|
509
|
+
|
510
|
+
def has_limit_or_offset? # :nodoc:
|
511
|
+
limit_value || offset_value
|
512
|
+
end
|
513
|
+
|
514
|
+
def alias_tracker(joins = [], aliases = nil) # :nodoc:
|
515
|
+
joins += [aliases] if aliases
|
516
|
+
ActiveRecord::Associations::AliasTracker.create(connection, table.name, joins)
|
517
|
+
end
|
518
|
+
|
646
519
|
protected
|
647
520
|
|
648
521
|
def load_records(records)
|
@@ -657,20 +530,44 @@ module ActiveRecord
|
|
657
530
|
end
|
658
531
|
|
659
532
|
def exec_queries(&block)
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
533
|
+
skip_query_cache_if_necessary do
|
534
|
+
@records =
|
535
|
+
if eager_loading?
|
536
|
+
apply_join_dependency do |relation, join_dependency|
|
537
|
+
if ActiveRecord::NullRelation === relation
|
538
|
+
[]
|
539
|
+
else
|
540
|
+
rows = connection.select_all(relation.arel, "SQL")
|
541
|
+
join_dependency.instantiate(rows, &block)
|
542
|
+
end.freeze
|
543
|
+
end
|
544
|
+
else
|
545
|
+
klass.find_by_sql(arel, &block).freeze
|
546
|
+
end
|
547
|
+
|
548
|
+
preload = preload_values
|
549
|
+
preload += includes_values unless eager_loading?
|
550
|
+
preloader = nil
|
551
|
+
preload.each do |associations|
|
552
|
+
preloader ||= build_preloader
|
553
|
+
preloader.preload @records, associations
|
554
|
+
end
|
669
555
|
|
670
|
-
|
556
|
+
@records.each(&:readonly!) if readonly_value
|
671
557
|
|
672
|
-
|
673
|
-
|
558
|
+
@loaded = true
|
559
|
+
@records
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
def skip_query_cache_if_necessary
|
564
|
+
if skip_query_cache_value
|
565
|
+
uncached do
|
566
|
+
yield
|
567
|
+
end
|
568
|
+
else
|
569
|
+
yield
|
570
|
+
end
|
674
571
|
end
|
675
572
|
|
676
573
|
def build_preloader
|
data/lib/active_record/result.rb
CHANGED