activerecord 5.1.5 → 5.1.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: c959975b61990368b7c19d60de2e6ac341e8962fe5ec6612f2c7246916343200
4
- data.tar.gz: 38b6c9d5f665a16158f3e3a663c8d1935f925d086a1b0bb954f68b94ba7c1fd0
2
+ SHA1:
3
+ metadata.gz: 20d95cb50f8968c49c4523fad400c5915593309a
4
+ data.tar.gz: e7db2becb08fc184a360c1b461dfcb008b636cf7
5
5
  SHA512:
6
- metadata.gz: 154de32a9ce2ffabd8a5b33d067e206b5be1d3b50c556e361b5018ce91cf534df778537aa46e2c2e7d7e616bb0e0ded3d62ad29b3f133c1565c53e615aff1de7
7
- data.tar.gz: 42d3009be5bf1eb2c57fd712d4cfa414560bc3f0dd74d180aacb2d888f907203973f07cdf362d4ebbd1ecbf7855ae08aabe8ae9f49e6d361dd2cb840333e723a
6
+ metadata.gz: e0f7d12872197c488a5313cd9d269b7b575acb78e3523afc004eb356832a8a29568dce7b3919050544121bbd8f7ef01f63362a095393b8f6e5481e6f0ab8647d
7
+ data.tar.gz: d073aad1fd735f8eb2ecf45418957333e9cc15c62be828ec12960dd9f1dac7506bdbc11a031608e99c51f9cb4ff466fc9fc4e9f6ecf21cc6f72d4919e02565a3
@@ -1,5 +1,57 @@
1
+ ## Rails 5.1.6 (March 29, 2018) ##
2
+
3
+ * MySQL: Support mysql2 0.5.x.
4
+
5
+ *Aaron Stone*
6
+
7
+ * Apply time column precision on assignment.
8
+
9
+ PR #20317 changed the behavior of datetime columns so that when they
10
+ have a specified precision then on assignment the value is rounded to
11
+ that precision. This behavior is now applied to time columns as well.
12
+
13
+ Fixes #30301.
14
+
15
+ *Andrew White*
16
+
17
+ * Normalize time column values for SQLite database.
18
+
19
+ For legacy reasons, time columns in SQLite are stored as full datetimes
20
+ because until #24542 the quoting for time columns didn't remove the date
21
+ component. To ensure that values are consistent we now normalize the
22
+ date component to 2001-01-01 on reading and writing.
23
+
24
+ *Andrew White*
25
+
26
+ * Ensure that the date component is removed when quoting times.
27
+
28
+ PR #24542 altered the quoting for time columns so that the date component
29
+ was removed however it only removed it when it was 2001-01-01. Now the
30
+ date component is removed irrespective of what the date is.
31
+
32
+ *Andrew White*
33
+
34
+ * Fix that after commit callbacks on update does not triggered when optimistic locking is enabled.
35
+
36
+ *Ryuta Kamizono*
37
+
38
+ * `ActiveRecord::Persistence#touch` does not work well when optimistic locking enabled and
39
+ `locking_column`, without default value, is null in the database.
40
+
41
+ *bogdanvlviv*
42
+
43
+ * Fix destroying existing object does not work well when optimistic locking enabled and
44
+ `locking column` is null in the database.
45
+
46
+ *bogdanvlviv*
47
+
48
+
1
49
  ## Rails 5.1.5 (February 14, 2018) ##
2
50
 
51
+ * PostgreSQL: Allow pg-1.0 gem to be used with Active Record.
52
+
53
+ *Lars Kanis*
54
+
3
55
  * Fix `count(:all)` with eager loading and having an order other than the driving table.
4
56
 
5
57
  Fixes #31783.
@@ -3,7 +3,7 @@ require "active_record/attribute_set/yaml_encoder"
3
3
 
4
4
  module ActiveRecord
5
5
  class AttributeSet # :nodoc:
6
- delegate :each_value, :fetch, to: :attributes
6
+ delegate :each_value, :fetch, :except, to: :attributes
7
7
 
8
8
  def initialize(attributes)
9
9
  @attributes = attributes
@@ -3,35 +3,30 @@ require "active_record/attribute"
3
3
  module ActiveRecord
4
4
  class AttributeSet # :nodoc:
5
5
  class Builder # :nodoc:
6
- attr_reader :types, :always_initialized, :default
6
+ attr_reader :types, :default_attributes
7
7
 
8
- def initialize(types, always_initialized = nil, &default)
8
+ def initialize(types, default_attributes = {})
9
9
  @types = types
10
- @always_initialized = always_initialized
11
- @default = default
10
+ @default_attributes = default_attributes
12
11
  end
13
12
 
14
13
  def build_from_database(values = {}, additional_types = {})
15
- if always_initialized && !values.key?(always_initialized)
16
- values[always_initialized] = nil
17
- end
18
-
19
- attributes = LazyAttributeHash.new(types, values, additional_types, &default)
14
+ attributes = LazyAttributeHash.new(types, values, additional_types, default_attributes)
20
15
  AttributeSet.new(attributes)
21
16
  end
22
17
  end
23
18
  end
24
19
 
25
20
  class LazyAttributeHash # :nodoc:
26
- delegate :transform_values, :each_key, :each_value, :fetch, to: :materialize
21
+ delegate :transform_values, :each_key, :each_value, :fetch, :except, to: :materialize
27
22
 
28
- def initialize(types, values, additional_types, &default)
23
+ def initialize(types, values, additional_types, default_attributes, delegate_hash = {})
29
24
  @types = types
30
25
  @values = values
31
26
  @additional_types = additional_types
32
27
  @materialized = false
33
- @delegate_hash = {}
34
- @default = default || proc {}
28
+ @delegate_hash = delegate_hash
29
+ @default_attributes = default_attributes
35
30
  end
36
31
 
37
32
  def key?(key)
@@ -79,22 +74,24 @@ module ActiveRecord
79
74
  end
80
75
 
81
76
  def marshal_dump
82
- materialize
77
+ [@types, @values, @additional_types, @default_attributes, @delegate_hash]
83
78
  end
84
79
 
85
- def marshal_load(delegate_hash)
86
- @delegate_hash = delegate_hash
87
- @types = {}
88
- @values = {}
89
- @additional_types = {}
90
- @materialized = true
80
+ def marshal_load(values)
81
+ if values.is_a?(Hash)
82
+ empty_hash = {}.freeze
83
+ initialize(empty_hash, empty_hash, empty_hash, empty_hash, values)
84
+ @materialized = true
85
+ else
86
+ initialize(*values)
87
+ end
91
88
  end
92
89
 
93
90
  # TODO Change this to private once we've dropped Ruby 2.2 support.
94
91
  # Workaround for Ruby 2.2 "private attribute?" warning.
95
92
  protected
96
93
 
97
- attr_reader :types, :values, :additional_types, :delegate_hash, :default
94
+ attr_reader :types, :values, :additional_types, :delegate_hash, :default_attributes
98
95
 
99
96
  def materialize
100
97
  unless @materialized
@@ -117,7 +114,12 @@ module ActiveRecord
117
114
  if value_present
118
115
  delegate_hash[name] = Attribute.from_database(name, value, type)
119
116
  elsif types.key?(name)
120
- delegate_hash[name] = default.call(name) || Attribute.uninitialized(name, type)
117
+ attr = default_attributes[name]
118
+ if attr
119
+ delegate_hash[name] = attr.dup
120
+ else
121
+ delegate_hash[name] = Attribute.uninitialized(name, type)
122
+ end
121
123
  end
122
124
  end
123
125
  end
@@ -56,7 +56,7 @@ module ActiveRecord
56
56
  # store_listing = StoreListing.new(price_in_cents: '10.1')
57
57
  #
58
58
  # # before
59
- # store_listing.price_in_cents # => BigDecimal.new(10.1)
59
+ # store_listing.price_in_cents # => BigDecimal(10.1)
60
60
  #
61
61
  # class StoreListing < ActiveRecord::Base
62
62
  # attribute :price_in_cents, :integer
@@ -152,7 +152,7 @@ module ActiveRecord
152
152
  end
153
153
 
154
154
  def quoted_time(value) # :nodoc:
155
- quoted_date(value).sub(/\A2000-01-01 /, "")
155
+ quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "")
156
156
  end
157
157
 
158
158
  def quoted_binary(value) # :nodoc:
@@ -1,7 +1,7 @@
1
1
  require "active_record/connection_adapters/abstract_mysql_adapter"
2
2
  require "active_record/connection_adapters/mysql/database_statements"
3
3
 
4
- gem "mysql2", ">= 0.3.18", "< 0.5"
4
+ gem "mysql2", ">= 0.3.18", "< 0.6.0"
5
5
  require "mysql2"
6
6
  raise "mysql2 0.4.3 is not supported. Please upgrade to 0.4.4+" if Mysql2::VERSION == "0.4.3"
7
7
 
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  module OID # :nodoc:
5
5
  class Decimal < Type::Decimal # :nodoc:
6
6
  def infinity(options = {})
7
- BigDecimal.new("Infinity") * (options[:negative] ? -1 : 1)
7
+ BigDecimal("Infinity") * (options[:negative] ? -1 : 1)
8
8
  end
9
9
  end
10
10
  end
@@ -122,7 +122,7 @@ module ActiveRecord
122
122
  comment = row[5]
123
123
  opclass = row[6]
124
124
 
125
- using, expressions, where = inddef.scan(/ USING (\w+?) \((.+?)\)(?: WHERE (.+))?\z/).flatten
125
+ using, expressions, where = inddef.scan(/ USING (\w+?) \((.+?)\)(?: WHERE (.+))?\z/m).flatten
126
126
 
127
127
  if indkey.include?(0) || opclass > 0
128
128
  columns = expressions
@@ -15,7 +15,7 @@ module ActiveRecord
15
15
  end
16
16
 
17
17
  def quoted_time(value)
18
- quoted_date(value)
18
+ quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ")
19
19
  end
20
20
 
21
21
  def quoted_binary(value)
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  module VERSION
8
8
  MAJOR = 5
9
9
  MINOR = 1
10
- TINY = 5
10
+ TINY = 6
11
11
  PRE = nil
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -60,13 +60,6 @@ module ActiveRecord
60
60
  end
61
61
 
62
62
  private
63
-
64
- def increment_lock
65
- lock_col = self.class.locking_column
66
- previous_lock_value = send(lock_col).to_i
67
- send(lock_col + "=", previous_lock_value + 1)
68
- end
69
-
70
63
  def _create_record(attribute_names = self.attribute_names, *)
71
64
  if locking_enabled?
72
65
  # We always want to persist the locking version, even if we don't detect
@@ -76,39 +69,37 @@ module ActiveRecord
76
69
  super
77
70
  end
78
71
 
79
- def _update_record(attribute_names = self.attribute_names)
72
+ def _touch_row(attribute_names, time)
73
+ super
74
+ ensure
75
+ clear_attribute_change(self.class.locking_column) if locking_enabled?
76
+ end
77
+
78
+ def _update_row(attribute_names, attempted_action = "update")
80
79
  return super unless locking_enabled?
81
- return 0 if attribute_names.empty?
82
80
 
83
81
  begin
84
- lock_col = self.class.locking_column
85
-
86
- previous_lock_value = read_attribute_before_type_cast(lock_col)
87
-
88
- increment_lock
89
-
90
- attribute_names.push(lock_col)
82
+ locking_column = self.class.locking_column
83
+ previous_lock_value = read_attribute_before_type_cast(locking_column)
84
+ attribute_names << locking_column
91
85
 
92
- relation = self.class.unscoped
86
+ self[locking_column] += 1
93
87
 
94
- affected_rows = relation.where(
95
- self.class.primary_key => id,
96
- lock_col => previous_lock_value
97
- ).update_all(
98
- attributes_for_update(attribute_names).map do |name|
99
- [name, _read_attribute(name)]
100
- end.to_h
88
+ affected_rows = self.class.unscoped._update_record(
89
+ arel_attributes_with_values(attribute_names),
90
+ self.class.primary_key => id_in_database,
91
+ locking_column => previous_lock_value
101
92
  )
102
93
 
103
- unless affected_rows == 1
104
- raise ActiveRecord::StaleObjectError.new(self, "update")
94
+ if affected_rows != 1
95
+ raise ActiveRecord::StaleObjectError.new(self, attempted_action)
105
96
  end
106
97
 
107
98
  affected_rows
108
99
 
109
100
  # If something went wrong, revert the locking_column value.
110
101
  rescue Exception
111
- send(lock_col + "=", previous_lock_value.to_i)
102
+ self[locking_column] = previous_lock_value.to_i
112
103
  raise
113
104
  end
114
105
  end
@@ -128,7 +119,7 @@ module ActiveRecord
128
119
 
129
120
  if locking_enabled?
130
121
  locking_column = self.class.locking_column
131
- relation = relation.where(locking_column => _read_attribute(locking_column))
122
+ relation = relation.where(locking_column => read_attribute_before_type_cast(locking_column))
132
123
  end
133
124
 
134
125
  relation
@@ -332,11 +332,11 @@ module ActiveRecord
332
332
  end
333
333
 
334
334
  def attributes_builder # :nodoc:
335
- @attributes_builder ||= AttributeSet::Builder.new(attribute_types, primary_key) do |name|
336
- unless columns_hash.key?(name)
337
- _default_attributes[name].dup
338
- end
335
+ unless defined?(@attributes_builder) && @attributes_builder
336
+ defaults = _default_attributes.except(*(column_names - [primary_key]))
337
+ @attributes_builder = AttributeSet::Builder.new(attribute_types, defaults)
339
338
  end
339
+ @attributes_builder
340
340
  end
341
341
 
342
342
  def columns_hash # :nodoc:
@@ -505,36 +505,12 @@ module ActiveRecord
505
505
  MSG
506
506
  end
507
507
 
508
- time ||= current_time_from_proper_timezone
509
- attributes = timestamp_attributes_for_update_in_model
510
- attributes.concat(names)
511
-
512
- unless attributes.empty?
513
- changes = {}
514
-
515
- attributes.each do |column|
516
- column = column.to_s
517
- changes[column] = write_attribute(column, time)
518
- end
519
-
520
- primary_key = self.class.primary_key
521
- scope = self.class.unscoped.where(primary_key => _read_attribute(primary_key))
522
-
523
- if locking_enabled?
524
- locking_column = self.class.locking_column
525
- scope = scope.where(locking_column => _read_attribute(locking_column))
526
- changes[locking_column] = increment_lock
527
- end
528
-
529
- clear_attribute_changes(changes.keys)
530
- result = scope.update_all(changes) == 1
531
-
532
- if !result && locking_enabled?
533
- raise ActiveRecord::StaleObjectError.new(self, "touch")
534
- end
508
+ attribute_names = timestamp_attributes_for_update_in_model
509
+ attribute_names.concat(names)
535
510
 
536
- @_trigger_update_callback = result
537
- result
511
+ unless attribute_names.empty?
512
+ affected_rows = _touch_row(attribute_names, time)
513
+ @_trigger_update_callback = affected_rows == 1
538
514
  else
539
515
  true
540
516
  end
@@ -554,6 +530,24 @@ module ActiveRecord
554
530
  self.class.unscoped.where(self.class.primary_key => id)
555
531
  end
556
532
 
533
+ def _touch_row(attribute_names, time)
534
+ time ||= current_time_from_proper_timezone
535
+
536
+ attribute_names.each do |attr_name|
537
+ write_attribute(attr_name, time)
538
+ clear_attribute_change(attr_name)
539
+ end
540
+
541
+ _update_row(attribute_names, "touch")
542
+ end
543
+
544
+ def _update_row(attribute_names, attempted_action = "update")
545
+ self.class.unscoped._update_record(
546
+ arel_attributes_with_values(attribute_names),
547
+ self.class.primary_key => id_in_database
548
+ )
549
+ end
550
+
557
551
  def create_or_update(*args, &block)
558
552
  _raise_readonly_record_error if readonly?
559
553
  result = new_record? ? _create_record(&block) : _update_record(*args, &block)
@@ -563,23 +557,26 @@ module ActiveRecord
563
557
  # Updates the associated record with values matching those of the instance attributes.
564
558
  # Returns the number of affected rows.
565
559
  def _update_record(attribute_names = self.attribute_names)
566
- attributes_values = arel_attributes_with_values_for_update(attribute_names)
567
- if attributes_values.empty?
568
- rows_affected = 0
560
+ attribute_names &= self.class.column_names
561
+ attribute_names = attributes_for_update(attribute_names)
562
+
563
+ if attribute_names.empty?
564
+ affected_rows = 0
569
565
  @_trigger_update_callback = true
570
566
  else
571
- rows_affected = self.class.unscoped._update_record attributes_values, id, id_in_database
572
- @_trigger_update_callback = rows_affected > 0
567
+ affected_rows = _update_row(attribute_names)
568
+ @_trigger_update_callback = affected_rows == 1
573
569
  end
574
570
 
575
571
  yield(self) if block_given?
576
572
 
577
- rows_affected
573
+ affected_rows
578
574
  end
579
575
 
580
576
  # Creates a record with values matching those of the instance attributes
581
577
  # and returns its id.
582
578
  def _create_record(attribute_names = self.attribute_names)
579
+ attribute_names &= self.class.column_names
583
580
  attributes_values = arel_attributes_with_values_for_create(attribute_names)
584
581
 
585
582
  new_id = self.class.unscoped.insert attributes_values
@@ -5,20 +5,20 @@ module ActiveRecord
5
5
  # Enable the query cache within the block if Active Record is configured.
6
6
  # If it's not, it will execute the given block.
7
7
  def cache(&block)
8
- if configurations.empty?
9
- yield
10
- else
8
+ if connected? || !configurations.empty?
11
9
  connection.cache(&block)
10
+ else
11
+ yield
12
12
  end
13
13
  end
14
14
 
15
15
  # Disable the query cache within the block if Active Record is configured.
16
16
  # If it's not, it will execute the given block.
17
17
  def uncached(&block)
18
- if configurations.empty?
19
- yield
20
- else
18
+ if connected? || !configurations.empty?
21
19
  connection.uncached(&block)
20
+ else
21
+ yield
22
22
  end
23
23
  end
24
24
  end
@@ -67,7 +67,7 @@ module ActiveRecord
67
67
  binds)
68
68
  end
69
69
 
70
- def _update_record(values, id, id_was) # :nodoc:
70
+ def _update_record(values, constraints) # :nodoc:
71
71
  substitutes, binds = substitute_values values
72
72
 
73
73
  scope = @klass.unscoped
@@ -76,7 +76,7 @@ module ActiveRecord
76
76
  scope.unscope!(where: @klass.inheritance_column)
77
77
  end
78
78
 
79
- relation = scope.where(@klass.primary_key => (id_was || id))
79
+ relation = scope.where(constraints)
80
80
  bvs = binds + relation.bound_attributes
81
81
  um = relation
82
82
  .arel
@@ -112,7 +112,7 @@ module ActiveRecord
112
112
  if has_include?(column_name)
113
113
  relation = construct_relation_for_association_calculations
114
114
 
115
- if operation.to_s.downcase == "count" && !distinct_value
115
+ if operation.to_s.downcase == "count"
116
116
  relation.distinct!
117
117
  # PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
118
118
  if (column_name == :all || column_name.nil?) && select_values.empty?
@@ -17,7 +17,7 @@ module ActiveRecord
17
17
  relation = build_relation(finder_class, attribute, value)
18
18
  if record.persisted?
19
19
  if finder_class.primary_key
20
- relation = relation.where.not(finder_class.primary_key => record.id_in_database || record.id)
20
+ relation = relation.where.not(finder_class.primary_key => record.id_in_database)
21
21
  else
22
22
  raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
23
23
  end
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.5
4
+ version: 5.1.6
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-02-14 00:00:00.000000000 Z
11
+ date: 2018-03-29 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.5
19
+ version: 5.1.6
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.5
26
+ version: 5.1.6
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.5
33
+ version: 5.1.6
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.5
40
+ version: 5.1.6
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.5/activerecord
324
- changelog_uri: https://github.com/rails/rails/blob/v5.1.5/activerecord/CHANGELOG.md
323
+ source_code_uri: https://github.com/rails/rails/tree/v5.1.6/activerecord
324
+ changelog_uri: https://github.com/rails/rails/blob/v5.1.6/activerecord/CHANGELOG.md
325
325
  post_install_message:
326
326
  rdoc_options:
327
327
  - "--main"
@@ -340,7 +340,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
340
340
  version: '0'
341
341
  requirements: []
342
342
  rubyforge_project:
343
- rubygems_version: 2.7.3
343
+ rubygems_version: 2.6.14
344
344
  signing_key:
345
345
  specification_version: 4
346
346
  summary: Object-relational mapper framework (part of Rails).