activerecord 5.1.6.2 → 5.1.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f7d7f393dad05614a4dfa079c2c2cd5039f982e94ceb51aadd8ecb1f41f3f25
4
- data.tar.gz: d775252d28438081a178830d79c13dc91f759e7c95c8e8da9b4f1dac9c63f786
3
+ metadata.gz: 6148c87ad69abae38d0fb9dc68a93a4e74245b8cab51655cae154aa9071378d2
4
+ data.tar.gz: ecb3927ddf8bd39369cbb54d53500388d08dbbb38d0a75d34cae258cdbea32ed
5
5
  SHA512:
6
- metadata.gz: 1fb86a32a86e7f7da584df0db7f9f0f262c2dcf98fffe11be80f404a3afab63076199de99e3df83a4dc0ab7774c0984193c1947653a8749487835e4a6ed22d2e
7
- data.tar.gz: 46e92ea138eab8f51ddbf9df23f5b65c99680cfd58fff5ab9ecdfec3eca70e7b8aae489d1d46e4edfa550aa9cc3f6587f44dd645d6549d2aa11b03be1390297c
6
+ metadata.gz: 6aa5d88e07b70625aa7bd6aa12a136abc80da1444a492076f72e7f44b4edaee4bf9c85dd44ae61f5d196f39da58739fbb9d93355fc4de2177af882a1932d8eaf
7
+ data.tar.gz: 59c1baec317ea025f115c975db9aaf5f89f96604a92d1e11c31ed8b5b1876946ccbd5f4ed396c29f841fb3c694f24f5bbff5412a6a9a73a92f97ceb244853d52
@@ -1,3 +1,20 @@
1
+ ## Rails 5.1.7.rc1 (March 22, 2019) ##
2
+
3
+ * Fix `touch` option to behave consistently with `Persistence#touch` method.
4
+
5
+ *Ryuta Kamizono*
6
+
7
+ * Back port Rails 5.2 `reverse_order` Arel SQL literal fix.
8
+
9
+ *Matt Jones*, *Brooke Kuhlmann*
10
+
11
+ * `becomes` should clear the mutation tracker which is created in `after_initialize`.
12
+
13
+ Fixes #32867.
14
+
15
+ *Ryuta Kamizono*
16
+
17
+
1
18
  ## Rails 5.1.6.2 (March 11, 2019) ##
2
19
 
3
20
  * No changes.
@@ -65,7 +65,7 @@ module ActiveRecord
65
65
  def update_counters_on_replace(record)
66
66
  if require_counter_update? && different_target?(record)
67
67
  owner.instance_variable_set :@_after_replace_counter_called, true
68
- record.increment!(reflection.counter_cache_column)
68
+ record.increment!(reflection.counter_cache_column, touch: reflection.options[:touch])
69
69
  decrement_counters
70
70
  end
71
71
  end
@@ -84,7 +84,8 @@ module ActiveRecord::Associations::Builder # :nodoc:
84
84
  else
85
85
  klass = association.klass
86
86
  end
87
- old_record = klass.find_by(klass.primary_key => old_foreign_id)
87
+ primary_key = reflection.association_primary_key(klass)
88
+ old_record = klass.find_by(primary_key => old_foreign_id)
88
89
 
89
90
  if old_record
90
91
  if touch != true
@@ -204,12 +204,12 @@ module ActiveRecord
204
204
 
205
205
  # Alias for `changed`
206
206
  def changed_attribute_names_to_save
207
- changes_to_save.keys
207
+ mutations_from_database.changed_attribute_names
208
208
  end
209
209
 
210
210
  # Alias for `changed_attributes`
211
211
  def attributes_in_database
212
- changes_to_save.transform_values(&:first)
212
+ mutations_from_database.changed_values
213
213
  end
214
214
 
215
215
  def attribute_was(*)
@@ -8,6 +8,10 @@ module ActiveRecord
8
8
  @deprecated_forced_changes = Set.new
9
9
  end
10
10
 
11
+ def changed_attribute_names
12
+ attr_names.select { |attr_name| changed?(attr_name) }
13
+ end
14
+
11
15
  def changed_values
12
16
  attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
13
17
  if changed?(attr_name)
@@ -20,7 +24,7 @@ module ActiveRecord
20
24
  attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
21
25
  change = change_to_attribute(attr_name)
22
26
  if change
23
- result[attr_name] = change
27
+ result.merge!(attr_name => change)
24
28
  end
25
29
  end
26
30
  end
@@ -82,6 +86,10 @@ module ActiveRecord
82
86
  class NullMutationTracker # :nodoc:
83
87
  include Singleton
84
88
 
89
+ def changed_attribute_names(*)
90
+ []
91
+ end
92
+
85
93
  def changed_values(*)
86
94
  {}
87
95
  end
@@ -330,6 +330,10 @@ module ActiveRecord
330
330
  _run_touch_callbacks { super }
331
331
  end
332
332
 
333
+ def increment!(attribute, by = 1, touch: nil) # :nodoc:
334
+ touch ? _run_touch_callbacks { super } : super
335
+ end
336
+
333
337
  private
334
338
 
335
339
  def create_or_update(*)
@@ -191,7 +191,9 @@ module ActiveRecord
191
191
  t0 = Time.now
192
192
  elapsed = 0
193
193
  loop do
194
- @cond.wait(timeout - elapsed)
194
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
195
+ @cond.wait(timeout - elapsed)
196
+ end
195
197
 
196
198
  return remove if any?
197
199
 
@@ -152,6 +152,7 @@ module ActiveRecord
152
152
  end
153
153
 
154
154
  def quoted_time(value) # :nodoc:
155
+ value = value.change(year: 2000, month: 1, day: 1)
155
156
  quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "")
156
157
  end
157
158
 
@@ -873,15 +873,25 @@ module ActiveRecord
873
873
  end
874
874
 
875
875
  def mismatched_foreign_key(message)
876
- parts = message.scan(/`(\w+)`[ $)]/).flatten
877
- MismatchedForeignKey.new(
878
- self,
876
+ match = %r/
877
+ (?:CREATE|ALTER)\s+TABLE\s*(?:`?\w+`?\.)?`?(?<table>\w+)`?.+?
878
+ FOREIGN\s+KEY\s*\(`?(?<foreign_key>\w+)`?\)\s*
879
+ REFERENCES\s*(`?(?<target_table>\w+)`?)\s*\(`?(?<primary_key>\w+)`?\)
880
+ /xmi.match(message)
881
+
882
+ options = {
879
883
  message: message,
880
- table: parts[0],
881
- foreign_key: parts[1],
882
- target_table: parts[2],
883
- primary_key: parts[3],
884
- )
884
+ }
885
+
886
+ if match
887
+ options[:table] = match[:table]
888
+ options[:foreign_key] = match[:foreign_key]
889
+ options[:target_table] = match[:target_table]
890
+ options[:primary_key] = match[:primary_key]
891
+ options[:primary_key_column] = column_for(match[:target_table], match[:primary_key])
892
+ end
893
+
894
+ MismatchedForeignKey.new(options)
885
895
  end
886
896
 
887
897
  def integer_to_sql(limit) # :nodoc:
@@ -31,7 +31,13 @@ module ActiveRecord
31
31
 
32
32
  def cast(value)
33
33
  if value.is_a?(::String)
34
- value = @pg_decoder.decode(value)
34
+ value = begin
35
+ @pg_decoder.decode(value)
36
+ rescue TypeError
37
+ # malformed array string is treated as [], will raise in PG 2.0 gem
38
+ # this keeps a consistent implementation
39
+ []
40
+ end
35
41
  end
36
42
  type_cast_array(value, :cast)
37
43
  end
@@ -64,6 +70,10 @@ module ActiveRecord
64
70
  deserialize(raw_old_value) != new_value
65
71
  end
66
72
 
73
+ def force_equality?(value)
74
+ value.is_a?(::Array)
75
+ end
76
+
67
77
  private
68
78
 
69
79
  def type_cast_array(value, method)
@@ -51,6 +51,10 @@ module ActiveRecord
51
51
  ::Range.new(new_begin, new_end, value.exclude_end?)
52
52
  end
53
53
 
54
+ def force_equality?(value)
55
+ value.is_a?(::Range)
56
+ end
57
+
54
58
  private
55
59
 
56
60
  def type_cast_single(value)
@@ -2,6 +2,14 @@
2
2
  gem "pg", ">= 0.18", "< 2.0"
3
3
  require "pg"
4
4
 
5
+ # Use async_exec instead of exec_params on pg versions before 1.1
6
+ class ::PG::Connection
7
+ unless self.public_method_defined?(:async_exec_params)
8
+ remove_method :exec_params
9
+ alias exec_params async_exec
10
+ end
11
+ end
12
+
5
13
  require "active_record/connection_adapters/abstract_adapter"
6
14
  require "active_record/connection_adapters/statement_pool"
7
15
  require "active_record/connection_adapters/postgresql/column"
@@ -613,7 +621,7 @@ module ActiveRecord
613
621
  type_casted_binds = type_casted_binds(binds)
614
622
  log(sql, name, binds, type_casted_binds) do
615
623
  ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
616
- @connection.async_exec(sql, type_casted_binds)
624
+ @connection.exec_params(sql, type_casted_binds)
617
625
  end
618
626
  end
619
627
  end
@@ -15,6 +15,7 @@ module ActiveRecord
15
15
  end
16
16
 
17
17
  def quoted_time(value)
18
+ value = value.change(year: 2000, month: 1, day: 1)
18
19
  quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ")
19
20
  end
20
21
 
@@ -7,7 +7,7 @@ require "active_record/connection_adapters/sqlite3/schema_definitions"
7
7
  require "active_record/connection_adapters/sqlite3/schema_dumper"
8
8
  require "active_record/connection_adapters/sqlite3/schema_statements"
9
9
 
10
- gem "sqlite3", "~> 1.3.6"
10
+ gem "sqlite3", "~> 1.3", ">= 1.3.6"
11
11
  require "sqlite3"
12
12
 
13
13
  module ActiveRecord
@@ -45,8 +45,12 @@ module ActiveRecord
45
45
  reflection = child_class._reflections.values.find { |e| e.belongs_to? && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
46
46
  counter_name = reflection.counter_cache_column
47
47
 
48
- updates = { counter_name.to_sym => object.send(counter_association).count(:all) }
49
- updates.merge!(touch_updates(touch)) if touch
48
+ updates = { counter_name => object.send(counter_association).count(:all) }
49
+
50
+ if touch
51
+ names = touch if touch != true
52
+ updates.merge!(touch_attributes_with_time(*names))
53
+ end
50
54
 
51
55
  unscoped.where(primary_key => object.id).update_all(updates)
52
56
  end
@@ -66,8 +70,8 @@ module ActiveRecord
66
70
  # * +counters+ - A Hash containing the names of the fields
67
71
  # to update as keys and the amount to update the field by as values.
68
72
  # * <tt>:touch</tt> option - Touch timestamp columns when updating.
69
- # Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
70
- # touch that column or an array of symbols to touch just those ones.
73
+ # If attribute names are passed, they are updated along with updated_at/on
74
+ # attributes.
71
75
  #
72
76
  # ==== Examples
73
77
  #
@@ -105,7 +109,8 @@ module ActiveRecord
105
109
  end
106
110
 
107
111
  if touch
108
- touch_updates = touch_updates(touch)
112
+ names = touch if touch != true
113
+ touch_updates = touch_attributes_with_time(*names)
109
114
  updates << sanitize_sql_for_assignment(touch_updates) unless touch_updates.empty?
110
115
  end
111
116
 
@@ -163,13 +168,6 @@ module ActiveRecord
163
168
  def decrement_counter(counter_name, id, touch: nil)
164
169
  update_counters(id, counter_name => -1, touch: touch)
165
170
  end
166
-
167
- private
168
- def touch_updates(touch)
169
- touch = timestamp_attributes_for_update_in_model if touch == true
170
- touch_time = current_time_from_proper_timezone
171
- Array(touch).map { |column| [ column, touch_time ] }.to_h
172
- end
173
171
  end
174
172
 
175
173
  private
@@ -115,16 +115,27 @@ module ActiveRecord
115
115
 
116
116
  # Raised when a foreign key constraint cannot be added because the column type does not match the referenced column type.
117
117
  class MismatchedForeignKey < StatementInvalid
118
- def initialize(adapter = nil, message: nil, table: nil, foreign_key: nil, target_table: nil, primary_key: nil)
119
- @adapter = adapter
118
+ def initialize(
119
+ adapter = nil,
120
+ message: nil,
121
+ sql: nil,
122
+ binds: nil,
123
+ table: nil,
124
+ foreign_key: nil,
125
+ target_table: nil,
126
+ primary_key: nil,
127
+ primary_key_column: nil
128
+ )
120
129
  if table
121
- msg = <<-EOM.strip_heredoc
122
- Column `#{foreign_key}` on table `#{table}` has a type of `#{column_type(table, foreign_key)}`.
123
- This does not match column `#{primary_key}` on `#{target_table}`, which has type `#{column_type(target_table, primary_key)}`.
124
- To resolve this issue, change the type of the `#{foreign_key}` column on `#{table}` to be :integer. (For example `t.integer #{foreign_key}`).
130
+ type = primary_key_column.bigint? ? :bigint : primary_key_column.type
131
+ msg = <<-EOM.squish
132
+ Column `#{foreign_key}` on table `#{table}` does not match column `#{primary_key}` on `#{target_table}`,
133
+ which has type `#{primary_key_column.sql_type}`.
134
+ To resolve this issue, change the type of the `#{foreign_key}` column on `#{table}` to be :#{type}.
135
+ (For example `t.#{type} :#{foreign_key}`).
125
136
  EOM
126
137
  else
127
- msg = <<-EOM
138
+ msg = <<-EOM.squish
128
139
  There is a mismatch between the foreign key and primary key column types.
129
140
  Verify that the foreign key column type and the primary key of the associated table match types.
130
141
  EOM
@@ -134,11 +145,6 @@ module ActiveRecord
134
145
  end
135
146
  super(msg)
136
147
  end
137
-
138
- private
139
- def column_type(table, column)
140
- @adapter.columns(table).detect { |c| c.name == column }.sql_type
141
- end
142
148
  end
143
149
 
144
150
  # Raised when a record cannot be inserted or updated because it would violate a not null constraint.
@@ -7,8 +7,8 @@ module ActiveRecord
7
7
  module VERSION
8
8
  MAJOR = 5
9
9
  MINOR = 1
10
- TINY = 6
11
- PRE = "2"
10
+ TINY = 7
11
+ PRE = "rc1"
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
14
  end
@@ -381,7 +381,7 @@ module ActiveRecord
381
381
  # default values when instantiating the Active Record object for this table.
382
382
  def column_defaults
383
383
  load_schema
384
- _default_attributes.to_hash
384
+ _default_attributes.deep_dup.to_hash
385
385
  end
386
386
 
387
387
  def _default_attributes # :nodoc:
@@ -226,7 +226,8 @@ module ActiveRecord
226
226
  def becomes(klass)
227
227
  became = klass.new
228
228
  became.instance_variable_set("@attributes", @attributes)
229
- became.instance_variable_set("@mutation_tracker", @mutation_tracker) if defined?(@mutation_tracker)
229
+ became.instance_variable_set("@mutation_tracker", @mutation_tracker ||= nil)
230
+ became.instance_variable_set("@mutations_from_database", @mutations_from_database ||= nil)
230
231
  became.instance_variable_set("@changed_attributes", attributes_changed_by_setter)
231
232
  became.instance_variable_set("@new_record", new_record?)
232
233
  became.instance_variable_set("@destroyed", destroyed?)
@@ -506,7 +507,7 @@ module ActiveRecord
506
507
  end
507
508
 
508
509
  attribute_names = timestamp_attributes_for_update_in_model
509
- attribute_names.concat(names)
510
+ attribute_names |= names.map(&:to_s)
510
511
 
511
512
  unless attribute_names.empty?
512
513
  affected_rows = _touch_row(attribute_names, time)
@@ -379,7 +379,7 @@ module ActiveRecord
379
379
 
380
380
  case conditions
381
381
  when Array, Hash
382
- relation.where!(conditions)
382
+ relation.where!(conditions) unless conditions.empty?
383
383
  else
384
384
  relation.where!(primary_key => conditions) unless conditions == :none
385
385
  end
@@ -429,7 +429,7 @@ module ActiveRecord
429
429
  raise UnknownPrimaryKey.new(@klass) if primary_key.nil?
430
430
 
431
431
  expects_array = ids.first.kind_of?(Array)
432
- return ids.first if expects_array && ids.first.empty?
432
+ return [] if expects_array && ids.first.empty?
433
433
 
434
434
  ids = ids.flatten.compact.uniq
435
435
 
@@ -95,7 +95,7 @@ module ActiveRecord
95
95
  next
96
96
  when value.is_a?(Relation)
97
97
  binds += value.bound_attributes
98
- when value.is_a?(Range) && !table.type(column_name).respond_to?(:subtype)
98
+ when value.is_a?(Range) && !table.type(column_name).force_equality?(value)
99
99
  first = value.begin
100
100
  last = value.end
101
101
  unless first.respond_to?(:infinite?) && first.infinite?
@@ -158,7 +158,7 @@ module ActiveRecord
158
158
  return if table.associated_with?(column_name)
159
159
  case value
160
160
  when Array, Range
161
- table.type(column_name).respond_to?(:subtype)
161
+ table.type(column_name).force_equality?(value)
162
162
  else
163
163
  !value.nil? && handler_for(value).is_a?(BasicObjectHandler)
164
164
  end
@@ -1079,7 +1079,7 @@ module ActiveRecord
1079
1079
  end
1080
1080
  o.split(",").map! do |s|
1081
1081
  s.strip!
1082
- s.gsub!(/\sasc\Z/i, " DESC") || s.gsub!(/\sdesc\Z/i, " ASC") || s.concat(" DESC")
1082
+ s.gsub!(/\sasc\Z/i, " DESC") || s.gsub!(/\sdesc\Z/i, " ASC") || (s << " DESC")
1083
1083
  end
1084
1084
  else
1085
1085
  o
@@ -120,7 +120,7 @@ module ActiveRecord
120
120
  $stderr.puts "Database '#{configuration['database']}' already exists"
121
121
  rescue Exception => error
122
122
  $stderr.puts error
123
- $stderr.puts "Couldn't create database for #{configuration.inspect}"
123
+ $stderr.puts "Couldn't create '#{configuration['database']}' database. Please check your configuration."
124
124
  raise
125
125
  end
126
126
 
@@ -53,6 +53,13 @@ module ActiveRecord
53
53
  end
54
54
 
55
55
  class_methods do
56
+ def touch_attributes_with_time(*names, time: nil)
57
+ attribute_names = timestamp_attributes_for_update_in_model
58
+ attribute_names |= names.map(&:to_s)
59
+ time ||= current_time_from_proper_timezone
60
+ attribute_names.each_with_object({}) { |attr_name, result| result[attr_name] = time }
61
+ end
62
+
56
63
  private
57
64
  def timestamp_attributes_for_create_in_model
58
65
  timestamp_attributes_for_create.select { |c| column_names.include?(c) }
@@ -49,6 +49,10 @@ module ActiveRecord
49
49
  end
50
50
  end
51
51
 
52
+ def force_equality?(value)
53
+ coder.respond_to?(:object_class) && value.is_a?(coder.object_class)
54
+ end
55
+
52
56
  private
53
57
 
54
58
  def default_value?(value)
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.1.6.2
4
+ version: 5.1.7.rc1
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: 2019-03-13 00:00:00.000000000 Z
11
+ date: 2019-03-22 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.1.6.2
19
+ version: 5.1.7.rc1
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.1.6.2
26
+ version: 5.1.7.rc1
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.1.6.2
33
+ version: 5.1.7.rc1
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.1.6.2
40
+ version: 5.1.7.rc1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: arel
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -320,8 +320,8 @@ homepage: http://rubyonrails.org
320
320
  licenses:
321
321
  - MIT
322
322
  metadata:
323
- source_code_uri: https://github.com/rails/rails/tree/v5.1.6.2/activerecord
324
- changelog_uri: https://github.com/rails/rails/blob/v5.1.6.2/activerecord/CHANGELOG.md
323
+ source_code_uri: https://github.com/rails/rails/tree/v5.1.7.rc1/activerecord
324
+ changelog_uri: https://github.com/rails/rails/blob/v5.1.7.rc1/activerecord/CHANGELOG.md
325
325
  post_install_message:
326
326
  rdoc_options:
327
327
  - "--main"
@@ -335,9 +335,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
335
335
  version: 2.2.2
336
336
  required_rubygems_version: !ruby/object:Gem::Requirement
337
337
  requirements:
338
- - - ">="
338
+ - - ">"
339
339
  - !ruby/object:Gem::Version
340
- version: '0'
340
+ version: 1.3.1
341
341
  requirements: []
342
342
  rubygems_version: 3.0.1
343
343
  signing_key: