activerecord 5.2.1 → 5.2.2
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 +107 -0
- data/lib/active_record/association_relation.rb +3 -3
- data/lib/active_record/associations/association.rb +8 -0
- data/lib/active_record/associations/collection_association.rb +5 -3
- data/lib/active_record/associations/has_many_association.rb +8 -0
- data/lib/active_record/associations/has_many_through_association.rb +22 -0
- data/lib/active_record/attribute_methods/dirty.rb +13 -8
- data/lib/active_record/autosave_association.rb +5 -5
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/collection_cache_key.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +5 -0
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -2
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +10 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +7 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +6 -2
- data/lib/active_record/connection_adapters/postgresql/utils.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +9 -1
- data/lib/active_record/enum.rb +1 -0
- data/lib/active_record/errors.rb +1 -1
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/model_schema.rb +1 -1
- data/lib/active_record/persistence.rb +6 -7
- data/lib/active_record/querying.rb +2 -1
- data/lib/active_record/railtie.rb +1 -3
- data/lib/active_record/relation.rb +26 -7
- data/lib/active_record/relation/delegation.rb +30 -0
- data/lib/active_record/relation/finder_methods.rb +2 -2
- data/lib/active_record/relation/merger.rb +2 -2
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/scoping/named.rb +2 -0
- data/lib/active_record/tasks/database_tasks.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38bf52e024134bc78c1daa8bf44ee21d685adcc62ddc9ded7feae3111c08a8e7
|
4
|
+
data.tar.gz: 89f9dbe14887a77a660722bb1a09ffbde6b11a4ab600b9a724458ac369548f09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0a17e48f08ba5082caa787efabf99f58bf0738de05a53f0fc4979ed27285f42f4f28e9406089f74845573f43d7a78718d5323bce8826a48d7bb673a77717055
|
7
|
+
data.tar.gz: '03572796340d73d6e9b1cfa04c1d10d84a528615e76d9e0f700af85086d4dad11c58e21ca96b8c44bddd303dd090a25e68489391046e6cd0b8cc7565d2393da8'
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,110 @@
|
|
1
|
+
## Rails 5.2.2 (December 04, 2018) ##
|
2
|
+
|
3
|
+
* Do not ignore the scoping with query methods in the scope block.
|
4
|
+
|
5
|
+
*Ryuta Kamizono*
|
6
|
+
|
7
|
+
* Allow aliased attributes to be used in `#update_columns` and `#update`.
|
8
|
+
|
9
|
+
*Gannon McGibbon*
|
10
|
+
|
11
|
+
* Allow spaces in postgres table names.
|
12
|
+
|
13
|
+
Fixes issue where "user post" is misinterpreted as "\"user\".\"post\"" when quoting table names with the postgres
|
14
|
+
adapter.
|
15
|
+
|
16
|
+
*Gannon McGibbon*
|
17
|
+
|
18
|
+
* Cached columns_hash fields should be excluded from ResultSet#column_types
|
19
|
+
|
20
|
+
PR #34528 addresses the inconsistent behaviour when attribute is defined for an ignored column. The following test
|
21
|
+
was passing for SQLite and MySQL, but failed for PostgreSQL:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
class DeveloperName < ActiveRecord::Type::String
|
25
|
+
def deserialize(value)
|
26
|
+
"Developer: #{value}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class AttributedDeveloper < ActiveRecord::Base
|
31
|
+
self.table_name = "developers"
|
32
|
+
|
33
|
+
attribute :name, DeveloperName.new
|
34
|
+
|
35
|
+
self.ignored_columns += ["name"]
|
36
|
+
end
|
37
|
+
|
38
|
+
developer = AttributedDeveloper.create
|
39
|
+
developer.update_column :name, "name"
|
40
|
+
|
41
|
+
loaded_developer = AttributedDeveloper.where(id: developer.id).select("*").first
|
42
|
+
puts loaded_developer.name # should be "Developer: name" but it's just "name"
|
43
|
+
```
|
44
|
+
|
45
|
+
*Dmitry Tsepelev*
|
46
|
+
|
47
|
+
* Values of enum are frozen, raising an error when attempting to modify them.
|
48
|
+
|
49
|
+
*Emmanuel Byrd*
|
50
|
+
|
51
|
+
* `update_columns` now correctly raises `ActiveModel::MissingAttributeError`
|
52
|
+
if the attribute does not exist.
|
53
|
+
|
54
|
+
*Sean Griffin*
|
55
|
+
|
56
|
+
* Do not use prepared statement in queries that have a large number of binds.
|
57
|
+
|
58
|
+
*Ryuta Kamizono*
|
59
|
+
|
60
|
+
* Fix query cache to load before first request.
|
61
|
+
|
62
|
+
*Eileen M. Uchitelle*
|
63
|
+
|
64
|
+
* Fix collection cache key with limit and custom select to avoid ambiguous timestamp column error.
|
65
|
+
|
66
|
+
Fixes #33056.
|
67
|
+
|
68
|
+
*Federico Martinez*
|
69
|
+
|
70
|
+
* Fix duplicated record creation when using nested attributes with `create_with`.
|
71
|
+
|
72
|
+
*Darwin Wu*
|
73
|
+
|
74
|
+
* Fix regression setting children record in parent `before_save` callback.
|
75
|
+
|
76
|
+
*Guo Xiang Tan*
|
77
|
+
|
78
|
+
* Prevent leaking of user's DB credentials on `rails db:create` failure.
|
79
|
+
|
80
|
+
*bogdanvlviv*
|
81
|
+
|
82
|
+
* Clear mutation tracker before continuing the around callbacks.
|
83
|
+
|
84
|
+
*Yuya Tanaka*
|
85
|
+
|
86
|
+
* Prevent deadlocks when waiting for connection from pool.
|
87
|
+
|
88
|
+
*Brent Wheeldon*
|
89
|
+
|
90
|
+
* Avoid extra scoping when using `Relation#update` that was causing this method to change the current scope.
|
91
|
+
|
92
|
+
*Ryuta Kamizono*
|
93
|
+
|
94
|
+
* Fix numericality validator not to be affected by custom getter.
|
95
|
+
|
96
|
+
*Ryuta Kamizono*
|
97
|
+
|
98
|
+
* Fix bulk change table ignores comment option on PostgreSQL.
|
99
|
+
|
100
|
+
*Yoshiyuki Kinjo*
|
101
|
+
|
102
|
+
|
103
|
+
## Rails 5.2.1.1 (November 27, 2018) ##
|
104
|
+
|
105
|
+
* No changes.
|
106
|
+
|
107
|
+
|
1
108
|
## Rails 5.2.1 (August 07, 2018) ##
|
2
109
|
|
3
110
|
* PostgreSQL: Support new relkind for partitioned tables.
|
@@ -31,9 +31,9 @@ module ActiveRecord
|
|
31
31
|
private
|
32
32
|
|
33
33
|
def exec_queries
|
34
|
-
super do |
|
35
|
-
@association.
|
36
|
-
yield
|
34
|
+
super do |record|
|
35
|
+
@association.set_inverse_instance_from_queries(record)
|
36
|
+
yield record if block_given?
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -103,6 +103,13 @@ module ActiveRecord
|
|
103
103
|
record
|
104
104
|
end
|
105
105
|
|
106
|
+
def set_inverse_instance_from_queries(record)
|
107
|
+
if inverse = inverse_association_for(record)
|
108
|
+
inverse.inversed_from_queries(owner)
|
109
|
+
end
|
110
|
+
record
|
111
|
+
end
|
112
|
+
|
106
113
|
# Remove the inverse association, if possible
|
107
114
|
def remove_inverse_instance(record)
|
108
115
|
if inverse = inverse_association_for(record)
|
@@ -114,6 +121,7 @@ module ActiveRecord
|
|
114
121
|
self.target = record
|
115
122
|
@inversed = !!record
|
116
123
|
end
|
124
|
+
alias :inversed_from_queries :inversed_from
|
117
125
|
|
118
126
|
# Returns the class of the target. belongs_to polymorphic overrides this to look at the
|
119
127
|
# polymorphic_type field on the owner.
|
@@ -45,6 +45,8 @@ module ActiveRecord
|
|
45
45
|
def ids_reader
|
46
46
|
if loaded?
|
47
47
|
target.pluck(reflection.association_primary_key)
|
48
|
+
elsif !target.empty?
|
49
|
+
load_target.pluck(reflection.association_primary_key)
|
48
50
|
else
|
49
51
|
@association_ids ||= scope.pluck(reflection.association_primary_key)
|
50
52
|
end
|
@@ -409,9 +411,9 @@ module ActiveRecord
|
|
409
411
|
end
|
410
412
|
|
411
413
|
def replace_records(new_target, original_target)
|
412
|
-
delete(target
|
414
|
+
delete(difference(target, new_target))
|
413
415
|
|
414
|
-
unless concat(new_target
|
416
|
+
unless concat(difference(new_target, target))
|
415
417
|
@target = original_target
|
416
418
|
raise RecordNotSaved, "Failed to replace #{reflection.name} because one or more of the " \
|
417
419
|
"new records could not be saved."
|
@@ -421,7 +423,7 @@ module ActiveRecord
|
|
421
423
|
end
|
422
424
|
|
423
425
|
def replace_common_records_in_memory(new_target, original_target)
|
424
|
-
common_records = new_target
|
426
|
+
common_records = intersection(new_target, original_target)
|
425
427
|
common_records.each do |record|
|
426
428
|
skip_callbacks = true
|
427
429
|
replace_on_target(record, @target.index(record), skip_callbacks)
|
@@ -163,6 +163,28 @@ module ActiveRecord
|
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
|
+
def difference(a, b)
|
167
|
+
distribution = distribution(b)
|
168
|
+
|
169
|
+
a.reject { |record| mark_occurrence(distribution, record) }
|
170
|
+
end
|
171
|
+
|
172
|
+
def intersection(a, b)
|
173
|
+
distribution = distribution(b)
|
174
|
+
|
175
|
+
a.select { |record| mark_occurrence(distribution, record) }
|
176
|
+
end
|
177
|
+
|
178
|
+
def mark_occurrence(distribution, record)
|
179
|
+
distribution[record] > 0 && distribution[record] -= 1
|
180
|
+
end
|
181
|
+
|
182
|
+
def distribution(array)
|
183
|
+
array.each_with_object(Hash.new(0)) do |record, distribution|
|
184
|
+
distribution[record] += 1
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
166
188
|
def through_records_for(record)
|
167
189
|
attributes = construct_join_attributes(record)
|
168
190
|
candidates = Array.wrap(through_association.target)
|
@@ -16,9 +16,6 @@ module ActiveRecord
|
|
16
16
|
|
17
17
|
class_attribute :partial_writes, instance_writer: false, default: true
|
18
18
|
|
19
|
-
after_create { changes_applied }
|
20
|
-
after_update { changes_applied }
|
21
|
-
|
22
19
|
# Attribute methods for "changed in last call to save?"
|
23
20
|
attribute_method_affix(prefix: "saved_change_to_", suffix: "?")
|
24
21
|
attribute_method_prefix("saved_change_to_")
|
@@ -123,18 +120,26 @@ module ActiveRecord
|
|
123
120
|
end
|
124
121
|
|
125
122
|
private
|
126
|
-
def write_attribute_without_type_cast(attr_name,
|
127
|
-
|
128
|
-
|
123
|
+
def write_attribute_without_type_cast(attr_name, value)
|
124
|
+
name = attr_name.to_s
|
125
|
+
if self.class.attribute_alias?(name)
|
126
|
+
name = self.class.attribute_alias(name)
|
127
|
+
end
|
128
|
+
result = super(name, value)
|
129
|
+
clear_attribute_change(name)
|
129
130
|
result
|
130
131
|
end
|
131
132
|
|
132
133
|
def _update_record(*)
|
133
|
-
partial_writes? ? super(keys_for_partial_write) : super
|
134
|
+
affected_rows = partial_writes? ? super(keys_for_partial_write) : super
|
135
|
+
changes_applied
|
136
|
+
affected_rows
|
134
137
|
end
|
135
138
|
|
136
139
|
def _create_record(*)
|
137
|
-
partial_writes? ? super(keys_for_partial_write) : super
|
140
|
+
id = partial_writes? ? super(keys_for_partial_write) : super
|
141
|
+
changes_applied
|
142
|
+
id
|
138
143
|
end
|
139
144
|
|
140
145
|
def keys_for_partial_write
|
@@ -392,7 +392,7 @@ module ActiveRecord
|
|
392
392
|
records -= records_to_destroy
|
393
393
|
end
|
394
394
|
|
395
|
-
records.
|
395
|
+
records.each do |record|
|
396
396
|
next if record.destroyed?
|
397
397
|
|
398
398
|
saved = true
|
@@ -401,11 +401,11 @@ module ActiveRecord
|
|
401
401
|
if autosave
|
402
402
|
saved = association.insert_record(record, false)
|
403
403
|
elsif !reflection.nested?
|
404
|
+
association_saved = association.insert_record(record)
|
405
|
+
|
404
406
|
if reflection.validate?
|
405
|
-
|
406
|
-
saved =
|
407
|
-
else
|
408
|
-
association.insert_record(record)
|
407
|
+
errors.add(reflection.name) unless association_saved
|
408
|
+
saved = association_saved
|
409
409
|
end
|
410
410
|
end
|
411
411
|
elsif autosave
|
@@ -20,9 +20,9 @@ module ActiveRecord
|
|
20
20
|
select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp"
|
21
21
|
|
22
22
|
if collection.has_limit_or_offset?
|
23
|
-
query = collection.select(column)
|
23
|
+
query = collection.select("#{column} AS collection_cache_key_timestamp")
|
24
24
|
subquery_alias = "subquery_for_cache_key"
|
25
|
-
subquery_column = "#{subquery_alias}
|
25
|
+
subquery_column = "#{subquery_alias}.collection_cache_key_timestamp"
|
26
26
|
subquery = query.arel.as(subquery_alias)
|
27
27
|
arel = Arel::SelectManager.new(subquery).project(select_values % subquery_column)
|
28
28
|
else
|
@@ -46,11 +46,16 @@ module ActiveRecord
|
|
46
46
|
def select_all(arel, name = nil, binds = [], preparable: nil)
|
47
47
|
arel = arel_from_relation(arel)
|
48
48
|
sql, binds = to_sql_and_binds(arel, binds)
|
49
|
+
|
49
50
|
if !prepared_statements || (arel.is_a?(String) && preparable.nil?)
|
50
51
|
preparable = false
|
52
|
+
elsif binds.length > bind_params_length
|
53
|
+
sql, binds = unprepared_statement { to_sql_and_binds(arel) }
|
54
|
+
preparable = false
|
51
55
|
else
|
52
56
|
preparable = visitor.preparable
|
53
57
|
end
|
58
|
+
|
54
59
|
if prepared_statements && preparable
|
55
60
|
select_prepared(sql, name, binds)
|
56
61
|
else
|
@@ -195,12 +195,12 @@ module ActiveRecord
|
|
195
195
|
if e.path == path_to_adapter
|
196
196
|
# We can assume that a non-builtin adapter was specified, so it's
|
197
197
|
# either misspelled or missing from Gemfile.
|
198
|
-
raise
|
198
|
+
raise LoadError, "Could not load the '#{spec[:adapter]}' Active Record adapter. Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary adapter gem to your Gemfile.", e.backtrace
|
199
199
|
|
200
200
|
# Bubbled up from the adapter require. Prefix the exception message
|
201
201
|
# with some guidance about how to address it and reraise.
|
202
202
|
else
|
203
|
-
raise
|
203
|
+
raise LoadError, "Error loading the '#{spec[:adapter]}' Active Record adapter. Missing a gem it depends on? #{e.message}", e.backtrace
|
204
204
|
end
|
205
205
|
end
|
206
206
|
|
@@ -10,8 +10,17 @@ module ActiveRecord
|
|
10
10
|
super
|
11
11
|
end
|
12
12
|
|
13
|
-
def visit_Arel_Nodes_In(
|
13
|
+
def visit_Arel_Nodes_In(o, collector)
|
14
14
|
@preparable = false
|
15
|
+
|
16
|
+
if Array === o.right && !o.right.empty?
|
17
|
+
o.right.delete_if do |bind|
|
18
|
+
if Arel::Nodes::BindParam === bind && Relation::QueryAttribute === bind.value
|
19
|
+
!bind.value.boundable?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
15
24
|
super
|
16
25
|
end
|
17
26
|
|
@@ -33,7 +33,13 @@ module ActiveRecord
|
|
33
33
|
|
34
34
|
def cast(value)
|
35
35
|
if value.is_a?(::String)
|
36
|
-
value =
|
36
|
+
value = begin
|
37
|
+
@pg_decoder.decode(value)
|
38
|
+
rescue TypeError
|
39
|
+
# malformed array string is treated as [], will raise in PG 2.0 gem
|
40
|
+
# this keeps a consistent implementation
|
41
|
+
[]
|
42
|
+
end
|
37
43
|
end
|
38
44
|
type_cast_array(value, :cast)
|
39
45
|
end
|
@@ -124,7 +124,7 @@ module ActiveRecord
|
|
124
124
|
|
125
125
|
# add info on sort order (only desc order is explicitly specified, asc is the default)
|
126
126
|
# and non-default opclasses
|
127
|
-
expressions.scan(/(?<column>\w+)
|
127
|
+
expressions.scan(/(?<column>\w+)"?\s?(?<opclass>\w+_ops)?\s?(?<desc>DESC)?\s?(?<nulls>NULLS (?:FIRST|LAST))?/).each do |column, opclass, desc, nulls|
|
128
128
|
opclasses[column] = opclass.to_sym if opclass
|
129
129
|
if nulls
|
130
130
|
orders[column] = [desc, nulls].compact.join(" ")
|
@@ -700,6 +700,11 @@ module ActiveRecord
|
|
700
700
|
sql
|
701
701
|
end
|
702
702
|
|
703
|
+
def add_column_for_alter(table_name, column_name, type, options = {})
|
704
|
+
return super unless options.key?(:comment)
|
705
|
+
[super, Proc.new { change_column_comment(table_name, column_name, options[:comment]) }]
|
706
|
+
end
|
707
|
+
|
703
708
|
def change_column_for_alter(table_name, column_name, type, options = {})
|
704
709
|
sqls = [change_column_sql(table_name, column_name, type, options)]
|
705
710
|
sqls << change_column_default_for_alter(table_name, column_name, options[:default]) if options.key?(:default)
|
@@ -708,7 +713,6 @@ module ActiveRecord
|
|
708
713
|
sqls
|
709
714
|
end
|
710
715
|
|
711
|
-
|
712
716
|
# Changes the default value of a table column.
|
713
717
|
def change_column_default_for_alter(table_name, column_name, default_or_changes) # :nodoc:
|
714
718
|
column = column_for(table_name, column_name)
|
@@ -68,7 +68,7 @@ module ActiveRecord
|
|
68
68
|
# * <tt>"schema_name".table_name</tt>
|
69
69
|
# * <tt>"schema.name"."table name"</tt>
|
70
70
|
def extract_schema_qualified_name(string)
|
71
|
-
schema, table = string.scan(/[^"
|
71
|
+
schema, table = string.scan(/[^".]+|"[^"]*"/)
|
72
72
|
if table.nil?
|
73
73
|
table = schema
|
74
74
|
schema = nil
|
@@ -4,6 +4,14 @@
|
|
4
4
|
gem "pg", ">= 0.18", "< 2.0"
|
5
5
|
require "pg"
|
6
6
|
|
7
|
+
# Use async_exec instead of exec_params on pg versions before 1.1
|
8
|
+
class ::PG::Connection
|
9
|
+
unless self.public_method_defined?(:async_exec_params)
|
10
|
+
remove_method :exec_params
|
11
|
+
alias exec_params async_exec
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
7
15
|
require "active_record/connection_adapters/abstract_adapter"
|
8
16
|
require "active_record/connection_adapters/statement_pool"
|
9
17
|
require "active_record/connection_adapters/postgresql/column"
|
@@ -600,7 +608,7 @@ module ActiveRecord
|
|
600
608
|
type_casted_binds = type_casted_binds(binds)
|
601
609
|
log(sql, name, binds, type_casted_binds) do
|
602
610
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
603
|
-
@connection.
|
611
|
+
@connection.exec_params(sql, type_casted_binds)
|
604
612
|
end
|
605
613
|
end
|
606
614
|
end
|
data/lib/active_record/enum.rb
CHANGED
data/lib/active_record/errors.rb
CHANGED
@@ -126,7 +126,7 @@ module ActiveRecord
|
|
126
126
|
To resolve this issue, change the type of the `#{foreign_key}` column on `#{table}` to be :integer. (For example `t.integer #{foreign_key}`).
|
127
127
|
EOM
|
128
128
|
else
|
129
|
-
msg = <<-EOM
|
129
|
+
msg = <<-EOM.strip_heredoc
|
130
130
|
There is a mismatch between the foreign key and primary key column types.
|
131
131
|
Verify that the foreign key column type and the primary key of the associated table match types.
|
132
132
|
EOM
|
@@ -1163,7 +1163,7 @@ module ActiveRecord
|
|
1163
1163
|
|
1164
1164
|
def migrations_path=(path)
|
1165
1165
|
ActiveSupport::Deprecation.warn \
|
1166
|
-
"ActiveRecord::Migrator.
|
1166
|
+
"`ActiveRecord::Migrator.migrations_path=` is now deprecated and will be removed in Rails 6.0. " \
|
1167
1167
|
"You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
|
1168
1168
|
self.migrations_paths = [path]
|
1169
1169
|
end
|
@@ -375,7 +375,7 @@ module ActiveRecord
|
|
375
375
|
# default values when instantiating the Active Record object for this table.
|
376
376
|
def column_defaults
|
377
377
|
load_schema
|
378
|
-
@column_defaults ||= _default_attributes.to_hash
|
378
|
+
@column_defaults ||= _default_attributes.deep_dup.to_hash
|
379
379
|
end
|
380
380
|
|
381
381
|
def _default_attributes # :nodoc:
|
@@ -97,13 +97,11 @@ module ActiveRecord
|
|
97
97
|
# When running callbacks is not needed for each record update,
|
98
98
|
# it is preferred to use {update_all}[rdoc-ref:Relation#update_all]
|
99
99
|
# for updating all records in a single query.
|
100
|
-
def update(id
|
100
|
+
def update(id, attributes)
|
101
101
|
if id.is_a?(Array)
|
102
102
|
id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
|
103
103
|
object.update(attributes[idx])
|
104
104
|
}
|
105
|
-
elsif id == :all
|
106
|
-
all.each { |record| record.update(attributes) }
|
107
105
|
else
|
108
106
|
if ActiveRecord::Base === id
|
109
107
|
raise ArgumentError,
|
@@ -473,15 +471,16 @@ module ActiveRecord
|
|
473
471
|
verify_readonly_attribute(key.to_s)
|
474
472
|
end
|
475
473
|
|
474
|
+
id_in_database = self.id_in_database
|
475
|
+
attributes.each do |k, v|
|
476
|
+
write_attribute_without_type_cast(k, v)
|
477
|
+
end
|
478
|
+
|
476
479
|
affected_rows = self.class._update_record(
|
477
480
|
attributes,
|
478
481
|
self.class.primary_key => id_in_database
|
479
482
|
)
|
480
483
|
|
481
|
-
attributes.each do |k, v|
|
482
|
-
write_attribute_without_type_cast(k, v)
|
483
|
-
end
|
484
|
-
|
485
484
|
affected_rows == 1
|
486
485
|
end
|
487
486
|
|
@@ -40,7 +40,8 @@ module ActiveRecord
|
|
40
40
|
def find_by_sql(sql, binds = [], preparable: nil, &block)
|
41
41
|
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
|
42
42
|
column_types = result_set.column_types.dup
|
43
|
-
|
43
|
+
cached_columns_hash = connection.schema_cache.columns_hash(table_name)
|
44
|
+
cached_columns_hash.each_key { |k| column_types.delete k }
|
44
45
|
message_bus = ActiveSupport::Notifications.instrumenter
|
45
46
|
|
46
47
|
payload = {
|
@@ -169,9 +169,7 @@ end_warning
|
|
169
169
|
end
|
170
170
|
|
171
171
|
initializer "active_record.set_executor_hooks" do
|
172
|
-
|
173
|
-
ActiveRecord::QueryCache.install_executor_hooks
|
174
|
-
end
|
172
|
+
ActiveRecord::QueryCache.install_executor_hooks
|
175
173
|
end
|
176
174
|
|
177
175
|
initializer "active_record.add_watchable_files" do |app|
|
@@ -54,7 +54,7 @@ module ActiveRecord
|
|
54
54
|
# user = users.new { |user| user.name = 'Oscar' }
|
55
55
|
# user.name # => Oscar
|
56
56
|
def new(attributes = nil, &block)
|
57
|
-
scoping { klass.new(
|
57
|
+
scoping { klass.new(values_for_create(attributes), &block) }
|
58
58
|
end
|
59
59
|
|
60
60
|
alias build new
|
@@ -82,7 +82,7 @@ module ActiveRecord
|
|
82
82
|
if attributes.is_a?(Array)
|
83
83
|
attributes.collect { |attr| create(attr, &block) }
|
84
84
|
else
|
85
|
-
scoping { klass.create(
|
85
|
+
scoping { klass.create(values_for_create(attributes), &block) }
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
@@ -96,7 +96,7 @@ module ActiveRecord
|
|
96
96
|
if attributes.is_a?(Array)
|
97
97
|
attributes.collect { |attr| create!(attr, &block) }
|
98
98
|
else
|
99
|
-
scoping { klass.create!(
|
99
|
+
scoping { klass.create!(values_for_create(attributes), &block) }
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
@@ -337,6 +337,14 @@ module ActiveRecord
|
|
337
337
|
@klass.connection.update stmt, "#{@klass} Update All"
|
338
338
|
end
|
339
339
|
|
340
|
+
def update(id = :all, attributes) # :nodoc:
|
341
|
+
if id == :all
|
342
|
+
each { |record| record.update(attributes) }
|
343
|
+
else
|
344
|
+
klass.update(id, attributes)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
340
348
|
# Destroys the records by instantiating each
|
341
349
|
# record and calling its {#destroy}[rdoc-ref:Persistence#destroy] method.
|
342
350
|
# Each object's callbacks are executed (including <tt>:dependent</tt> association options).
|
@@ -456,10 +464,8 @@ module ActiveRecord
|
|
456
464
|
where_clause.to_h(relation_table_name)
|
457
465
|
end
|
458
466
|
|
459
|
-
def scope_for_create
|
460
|
-
|
461
|
-
scope.merge!(attributes) if attributes
|
462
|
-
scope
|
467
|
+
def scope_for_create
|
468
|
+
where_values_hash.merge!(create_with_value.stringify_keys)
|
463
469
|
end
|
464
470
|
|
465
471
|
# Returns true if relation needs eager loading.
|
@@ -606,5 +612,18 @@ module ActiveRecord
|
|
606
612
|
# ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
|
607
613
|
string.scan(/([a-zA-Z_][.\w]+).?\./).flatten.map(&:downcase).uniq - ["raw_sql_"]
|
608
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
|
609
628
|
end
|
610
629
|
end
|
@@ -17,6 +17,7 @@ module ActiveRecord
|
|
17
17
|
delegate = Class.new(klass) {
|
18
18
|
include ClassSpecificRelation
|
19
19
|
}
|
20
|
+
include_relation_methods(delegate)
|
20
21
|
mangled_name = klass.name.gsub("::".freeze, "_".freeze)
|
21
22
|
const_set mangled_name, delegate
|
22
23
|
private_constant mangled_name
|
@@ -29,6 +30,35 @@ module ActiveRecord
|
|
29
30
|
child_class.initialize_relation_delegate_cache
|
30
31
|
super
|
31
32
|
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
def include_relation_methods(delegate)
|
36
|
+
superclass.include_relation_methods(delegate) unless base_class == self
|
37
|
+
delegate.include generated_relation_methods
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def generated_relation_methods
|
42
|
+
@generated_relation_methods ||= Module.new.tap do |mod|
|
43
|
+
mod_name = "GeneratedRelationMethods"
|
44
|
+
const_set mod_name, mod
|
45
|
+
private_constant mod_name
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def generate_relation_method(method)
|
50
|
+
if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method)
|
51
|
+
generated_relation_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
52
|
+
def #{method}(*args, &block)
|
53
|
+
scoping { klass.#{method}(*args, &block) }
|
54
|
+
end
|
55
|
+
RUBY
|
56
|
+
else
|
57
|
+
generated_relation_methods.send(:define_method, method) do |*args, &block|
|
58
|
+
scoping { klass.public_send(method, *args, &block) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
32
62
|
end
|
33
63
|
|
34
64
|
extend ActiveSupport::Concern
|
@@ -363,7 +363,7 @@ module ActiveRecord
|
|
363
363
|
|
364
364
|
case conditions
|
365
365
|
when Array, Hash
|
366
|
-
relation.where!(conditions)
|
366
|
+
relation.where!(conditions) unless conditions.empty?
|
367
367
|
else
|
368
368
|
relation.where!(primary_key => conditions) unless conditions == :none
|
369
369
|
end
|
@@ -417,7 +417,7 @@ module ActiveRecord
|
|
417
417
|
raise UnknownPrimaryKey.new(@klass) if primary_key.nil?
|
418
418
|
|
419
419
|
expects_array = ids.first.kind_of?(Array)
|
420
|
-
return
|
420
|
+
return [] if expects_array && ids.first.empty?
|
421
421
|
|
422
422
|
ids = ids.flatten.compact.uniq
|
423
423
|
|
@@ -156,10 +156,10 @@ module ActiveRecord
|
|
156
156
|
def merge_multi_values
|
157
157
|
if other.reordering_value
|
158
158
|
# override any order specified in the original relation
|
159
|
-
relation.reorder!
|
159
|
+
relation.reorder!(*other.order_values)
|
160
160
|
elsif other.order_values.any?
|
161
161
|
# merge in order_values from relation
|
162
|
-
relation.order!
|
162
|
+
relation.order!(*other.order_values)
|
163
163
|
end
|
164
164
|
|
165
165
|
extensions = other.extensions - relation.extensions
|
@@ -19,10 +19,10 @@ module ActiveRecord
|
|
19
19
|
when 0 then NullPredicate
|
20
20
|
when 1 then predicate_builder.build(attribute, values.first)
|
21
21
|
else
|
22
|
-
|
22
|
+
values.map! do |v|
|
23
23
|
predicate_builder.build_bind_attribute(attribute.name, v)
|
24
24
|
end
|
25
|
-
attribute.in(
|
25
|
+
values.empty? ? NullPredicate : attribute.in(values)
|
26
26
|
end
|
27
27
|
|
28
28
|
unless nils.empty?
|
@@ -8,7 +8,7 @@ module ActiveRecord
|
|
8
8
|
module SpawnMethods
|
9
9
|
# This is overridden by Associations::CollectionProxy
|
10
10
|
def spawn #:nodoc:
|
11
|
-
clone
|
11
|
+
@delegate_to_klass ? klass.all : clone
|
12
12
|
end
|
13
13
|
|
14
14
|
# Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
|
@@ -122,7 +122,7 @@ module ActiveRecord
|
|
122
122
|
$stderr.puts "Database '#{configuration['database']}' already exists"
|
123
123
|
rescue Exception => error
|
124
124
|
$stderr.puts error
|
125
|
-
$stderr.puts "Couldn't create database
|
125
|
+
$stderr.puts "Couldn't create '#{configuration['database']}' database. Please check your configuration."
|
126
126
|
raise
|
127
127
|
end
|
128
128
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.2.
|
4
|
+
version: 5.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.2.
|
19
|
+
version: 5.2.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 5.2.
|
26
|
+
version: 5.2.2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activemodel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 5.2.
|
33
|
+
version: 5.2.2
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 5.2.
|
40
|
+
version: 5.2.2
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: arel
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -307,8 +307,8 @@ homepage: http://rubyonrails.org
|
|
307
307
|
licenses:
|
308
308
|
- MIT
|
309
309
|
metadata:
|
310
|
-
source_code_uri: https://github.com/rails/rails/tree/v5.2.
|
311
|
-
changelog_uri: https://github.com/rails/rails/blob/v5.2.
|
310
|
+
source_code_uri: https://github.com/rails/rails/tree/v5.2.2/activerecord
|
311
|
+
changelog_uri: https://github.com/rails/rails/blob/v5.2.2/activerecord/CHANGELOG.md
|
312
312
|
post_install_message:
|
313
313
|
rdoc_options:
|
314
314
|
- "--main"
|