Skip to content

Ensure input to distance_of_time_in_words is not nil #20701

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 27, 2017

Conversation

iamvery
Copy link
Contributor

@iamvery iamvery commented Jun 25, 2015

Problem

The error message for bad input to the distance_of_time_in_words and related methods is cryptic. For example, if nil is provided as an argument to time_ago_in_words, this is the error:

irb> helper.time_ago_in_words(nil)
NoMethodError: undefined method `>' for nil:NilClass

I believe a more palatable result in this case would be to raise an ArgumentError for invalid input.

(Proposed) Solution

The provided implementation is a bit naive in that it only checks for nil arguments. While investigating the problem, I realized there are several different ways in which the input may be "bad".

  1. Argument is nil

  2. The from_time and to_time arguments are incompatible with one another. e.g.

    irb> helper.distance_of_time_in_words(Date.current, 0)
    ArgumentError: comparison of Time with 0 failed
  3. moar?

Generally it seems like the interface requires either two numeric arguments, or two to_time convertible arguments.

To that end, it felt like this issue may benefit from the input of parties more familiar with the code. I would be honored and willing to help with the solution. If I am able to come up with a more "elegant" solution to the type situation, I will gladly post it back here.

Thank you! 💫


TODO

  • settle on solution
  • update docs (if needed)
  • update changelog

@iamvery
Copy link
Contributor Author

iamvery commented Jun 26, 2015

Perhaps converting input to Numeric before any of the comparisons to avoid the mixed type case. Would that be weird? So assuming before this line there was something like:

from_time, to_time = from_time.to_f, to_time.to_f

You could do things like this, where it would normally be a comparison error:

irb> helper.distance_of_time_in_words(Time.now)
=> "over 45 years"
irb> helper.distance_of_time_in_words(0, Time.now)
=> "over 45 years"
irb> helper.distance_of_time_in_words(Time.now, 0)
=> "over 45 years"

Is that sane?

@iamvery
Copy link
Contributor Author

iamvery commented Aug 7, 2015

@sgrif is there anything I can do to improve this so that it gets some attention?

@gsamokovarov
Copy link
Contributor

Rails gets quite a lot of issues and pull requests. Give it a bit of time, people will catch up on the issue. Thank you so much for the work!

@rafaelfranca
Copy link
Member

Maybe changing:

from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)

to:

if from_time.respond_to?(:to_time)
  from_time = from_time.to_time
else
  from_time = from_time.to_f
end

if to_time.respond_to?(:to_time)
  to_time = to_time.to_time
else
  to_time = to_time.to_f
end

@iamvery
Copy link
Contributor Author

iamvery commented Aug 10, 2015

@gsamokovarov thanks for keeping me accountable! I can't imagine how overwhelming it must be to see so much activity on a project 😳

@rafaelfranca I believe that's still problematic, because the caller could pass one argument that is convertible to_time and another that is not. That would cause the ArgumentError: comparison of Time with ? failed I mentioned above.

Fundamentally I think the problem is to do with the method signature being so flexible (accepting both time and numeric values). I wonder if it'd be sane to convert all arguments to a common type (e.g. float) to deal with them uniformly inside the method?

options = {
scope: :'datetime.distance_in_words'
}.merge!(options)

from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
from_time, to_time = Time.at(from_time), Time.at(to_time)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is effectively a conversion of input to Time. One thing to note is that it's not timezone aware. The suite seemed happy locally so maybe it's not a concern since this method deals in relative times? Truth is I don't trust myself with time, so I'd love a sanity check on this...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pixeltrix WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fine - the two lines above convert any AS::TimeWithZone instances to local times so Time.at just essentially copies the values to a new Time instance. If there was a problem it's probably an underlying bug in to_time.

Thinking about it, maybe it might make things simpler if we define Numeric#to_time ? e.g:

class Numeric
  def to_time
    Time.at(self)
  end
end

This way we can eliminate the two Time.at calls, add a check for whether the two arguments respond to to_time and raise if they don't, eliminating the nil check.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By adding Numeric#to_time you could then make the method setup something like this:

def distance_of_time_in_words(from, to = 0, options = {})
  unless from.respond_to?(:to_time)
    raise ArgumentError, "from must be a time-like value"
  end

  unless to.respond_to?(:to_time)
    raise ArgumentError, "to must be a time-like value"
  end

  from_time, to_time = [from.to_time, to.to_time].sort
  distance_in_minutes = ((to_time - from_time)/60.0).round
  distance_in_seconds = (to_time - from_time).round

the exception messages could be better so feel free to change them

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very interesting idea! Would there be any concern that the Time conversion of Numeric values is always in local time? Is that confusing*?

* time is always so confusing 😞

@iamvery iamvery force-pushed the date-helper-argument-error branch from 2627419 to f1d3257 Compare August 11, 2015 13:12
@@ -5,6 +5,11 @@
require 'active_support/core_ext/date/acts_like'

class Numeric
# Convert number to local Time.
def to_time
Time.at(self)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any concern that Numeric conversions to Time are always left in local (system) time?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pixeltrix I think I feel like the numeric -> time conversion is too special-case to warrant making all numerics respond to to_time, even though it's still an explicit conversion. 😕

I guess my contention is that the choice of time unit & epoch are both domain concerns of Time, so it feels a stretch to leak them to Numeric. (Which I think might be more obvious once we expand this method's documentation to a workable level of detail.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was afraid of this. Shall I throw away those commits and stick with the implementation up to ec2e09b?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matthewd we support to_time on String which can be pretty much anything - in comparison to_time on Numeric is positively well defined. 😄

@iamvery to_time always returns a local time in the other places it's defined - in_time_zone is for AS::TWZ.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂 it's settled then!

:trollface:

@iamvery iamvery force-pushed the date-helper-argument-error branch from 2a8be0a to 67f57c3 Compare August 11, 2015 18:44
else
minutes_with_offset = distance_in_minutes
end
fyear = from_time.year
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we be a bit more explicit with these? It took me a minute to figure out what fyear meant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done! :)

@iamvery iamvery force-pushed the date-helper-argument-error branch from 55b9efa to 8b06c70 Compare August 12, 2015 12:07
@iamvery iamvery force-pushed the date-helper-argument-error branch from 8b06c70 to db19c93 Compare August 20, 2015 12:52
@iamvery iamvery force-pushed the date-helper-argument-error branch from db19c93 to 4c44b35 Compare November 21, 2015 03:33
@iamvery iamvery force-pushed the date-helper-argument-error branch from 4c44b35 to 9b1de29 Compare March 2, 2016 22:20
@iamvery
Copy link
Contributor Author

iamvery commented Mar 2, 2016

I run into this issue every time I'm teaching our Ruby course. I was reminded this week that the PR is still open. Any chance it can get some attention? Thanks! ❤️

@iamvery iamvery force-pushed the date-helper-argument-error branch 2 times, most recently from b0fd030 to 1cb1def Compare May 7, 2016 15:56
@iamvery iamvery force-pushed the date-helper-argument-error branch from 1cb1def to ed689eb Compare April 25, 2017 18:21
@iamvery
Copy link
Contributor Author

iamvery commented Apr 25, 2017

On a wave of inspiration from RailsConf, I got this PR freshly rebased! Would love to talk about getting it merged. Anyone want to hash it out in person? 💫

@pixeltrix
Copy link
Contributor

Discussed with @iamvery at RailsConf that implement to_time on Numeric is too risky so keeping any type conversion limited to the distance_of_time_in_words helper is key.

@iamvery
Copy link
Contributor Author

iamvery commented Apr 25, 2017

@pixeltrix updated!

@iamvery
Copy link
Contributor Author

iamvery commented Apr 25, 2017

There's a failure for Ruby 2.2.7, but it doesn't appear to be related?

from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
from_time = from_time.to_time
to_time = to_time.to_time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we could move this up to the start of the method and combine into if statements:

if from_time.is_a?(Numeric)
  from_time = Time.at(from_time)
elsif from_time.respond_to?(:to_time)
  from_time = from_time.to_time
else
  raise ArgumentError, "first argument must either be a time, date or numeric, was '#{from_time.inspect}'"
end

if to_time.is_a?(Numeric)
  to_time = Time.at(to_time)
elsif from_time.respond_to?(:to_time)
  to_time = to_time.to_time
else
  raise ArgumentError, "second argument must either be a time, date or numeric, was '#{to_time.inspect}'"
end

to_time = to_time.to_time
else
raise ArgumentError, "second argument must be convertible to_time"
end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd love to extract a small, private interface to perform this logic. Something like:

def normalize_to_time(value)
  if value.is_a?(Numeric)
    Time.at(value)
  elsif value.responds_to?(:to_time)
    value.to_time
  else
    yield(value) if block_given?
  end
end

Then we could replace these two similar blocks of code with something like:

from_time = normalize_to_time(from_time) { raise ArgumentError, "first argument must be convertible_to_time" }
to_time = normalize_to_time(to_time) { raise ArgumentError, "second argument must be convertible_to_time" }

The only reason that I didn't do that here is I'm not completely certain how Rails uses this module. If I put that in a private method, would it be accessible in the places where this module is included?

Anyway, that feels like it'd be a valuable change, but in the end I decided it might be better to discuss than me stumbling around trying to figure it out.

Thanks for the feedback in helping get this in!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't absolutely certain, so I was able to confirm that methods included from a module have access to private interfaces (I suppose they're also included?)

module Lol
  def wat
    haha
  end
  private
  def haha
    "OK"
  end
end

class Giggle
  include Lol
end

Giggle.new
=> #<Giggle:0x007ff69e0a1738>
Giggle.new.wat
=> "OK"

Copy link
Contributor

@pixeltrix pixeltrix Apr 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iamvery yes, that seems fine - I think the method name needs to be more specific to distance_of_time_in_words though as normalize_to_time seems quite generic.

Copy link
Contributor

@pixeltrix pixeltrix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you've fixed the two items it'll be good to merge so can you squash your commits, thanks 👍

@@ -91,12 +91,13 @@ module DateHelper
# distance_of_time_in_words(from_time, from_time + 50.minutes, scope: 'datetime.distance_in_words.short') # => "an hour"
# distance_of_time_in_words(from_time, from_time + 3.hours, scope: 'datetime.distance_in_words.short') # => "3 hours"
def distance_of_time_in_words(from_time, to_time = 0, options = {})
from_time = normalize_distance_of_time_argument_to_time(from_time)
to_time = normalize_distance_of_time_argument_to_time(to_time)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move these lines down underneath the options

@@ -687,6 +684,16 @@ def time_tag(date_or_time, *args, &block)

content_tag("time".freeze, content, options.reverse_merge(datetime: datetime), &block)
end

def normalize_distance_of_time_argument_to_time(value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be private so you'll need to add private and then indent again or rubocop will complain

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♂️

@iamvery iamvery force-pushed the date-helper-argument-error branch from 18a3a60 to afc3c25 Compare April 27, 2017 01:30
@@ -95,8 +95,8 @@ def distance_of_time_in_words(from_time, to_time = 0, options = {})
scope: :'datetime.distance_in_words'
}.merge!(options)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to mutate the new hash rather than doing options.merge(scope: :'datetime.distance_in_words')? I don't particularly care, just curious.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably performance reasons

@iamvery
Copy link
Contributor Author

iamvery commented Apr 27, 2017

@pixeltrix updated! do you want/need me to squash anything?


private

def normalize_distance_of_time_argument_to_time(value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to indent this otherwise code climate won't pass

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah hah, I'm not used to that style. Will fix and squash!

@pixeltrix
Copy link
Contributor

@iamvery yes, just the indentation fix and squash your commits please 👍

@iamvery iamvery force-pushed the date-helper-argument-error branch from afc3c25 to 8241ffd Compare April 27, 2017 03:50
@iamvery
Copy link
Contributor Author

iamvery commented Apr 27, 2017

@pixeltrix rebased the history into a more cohesive story. Let me know if you need anything else. Thanks for sticking with me through this! ❤️

elsif value.respond_to?(:to_time)
value.to_time
else
raise ArgumentError, "#{v} must be convertible to_time"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be raise ArgumentError, "#{value} must be convertible to_time" - getting a NameError when running the tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂 you'd think I'm tired or something

@pixeltrix
Copy link
Contributor

@iamvery can you squash to a single commit, please. For small changes like this it's cleaner that multiple commits if we need to revert, etc. and we can get the story you're telling from the PR. If we didn't do this it'd make navigating through git history much more painful when trying to do git bisect to find where a bug started, thanks.

@iamvery iamvery force-pushed the date-helper-argument-error branch from 8241ffd to 53148f3 Compare April 27, 2017 14:59
@iamvery
Copy link
Contributor Author

iamvery commented Apr 27, 2017

@pixeltrix you have been tremendously patient and helpful. Thank you for all your work to make and keep Rails great.

elsif value.respond_to?(:to_time)
value.to_time
else
raise ArgumentError, "#{value} must be convertible to_time"
Copy link
Contributor

@pixeltrix pixeltrix Apr 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last change, I promise 😄

Using #{value} with a nil value isn't helpful, e.g:

>> value = nil
>> "#{value} can't be converted to a Time value"
=> " can't be converted to a Time value"

It's better to use inspect:

>> value = nil
>> "#{value.inspect} can't be converted to a Time value"
=> "nil can't be converted to a Time value"

Can you also tweak the message to what I've used in this comment which is more in line with other similar Ruby messages, thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries at all! I'm honored to have gotten so much great feedback this week 💫 Updated 👊

* Internally all input is converted to time so that it can be treated
  uniformly.

Remove now-unneeded condition

* Now that all input is treated is converted to time, we no longer need
  to type check it.

Rename variables to clarify their purpose

Extract private method to normalize distance_of_time args to time

Update actionview changelog
@iamvery iamvery force-pushed the date-helper-argument-error branch from 53148f3 to 756de66 Compare April 27, 2017 19:00
@pixeltrix pixeltrix merged commit 2878f83 into rails:master Apr 27, 2017
@pixeltrix
Copy link
Contributor

@iamvery thanks for helping make Rails better 👍

@iamvery
Copy link
Contributor Author

iamvery commented Apr 27, 2017

👏 and you

@iamvery iamvery deleted the date-helper-argument-error branch April 27, 2017 20:57
bogdanvlviv added a commit to bogdanvlviv/rails that referenced this pull request Mar 18, 2018
- Remove
  ```
  *   Namespace error pages' CSS selectors to stop the styles from bleeding
      into other pages when using Turbolinks.
      ([Pull Request](rails#28814))
  ```
  since it was backported to
  `5-1-stable` by 50d5baf
  and
  `5-0-stable` by d1c4a39.

- Remove
  ```
  *   Allow irb options to be passed from `rails console` command.
      ([Pull Request](rails#29010))
  ```
  since it was backported to
  `5-1-stable` by e91b483.

- Remove
  ```
  *   Load environment file in `dbconsole` command.
      ([Pull Request](rails#29725))
  ```
  since it was backported to
  `5-1-stable` by 7f93428.

- Remove
  ```
  *   Gemfile for new apps: upgrade redis-rb from ~> 3.0 to 4.0.
      ([Pull Request](rails#30748))
  ```
  since it was backported to
  `5-1-stable` by 3789531.

- Remove
  ```
  *   Fix minitest rails plugin.
      The custom reporters are added only if needed.
      This will fix conflicts with others plugins.
      ([Commit](rails@ac99916))
  ```
  since it was backported to
  `5-1-stable` by caa7695.

- Remove
  ```
  *   Add support for compatibility with redis-rb gem for 4.0 version.
      ([Pull Request](rails#30748))
  ```
  since it was backported to
  `5-1-stable` by 3789531.

- Remove
  ```
  *   Add `action_controller_api` and `action_controller_base` load hooks to be
      called in `ActiveSupport.on_load`.
      ([Pull Request](rails#28402))
  ```
  since it was backported to
  `5-1-stable` by b9a5fd7.

- Remove
  ```
  *   `driven_by` now registers poltergeist and capybara-webkit.
      ([Pull Request](rails#29315))
  ```
  since it was backported to
  `5-1-stable` by c5dd451.

- Remove
  ```
  *   Fallback `ActionController::Parameters#to_s` to `Hash#to_s`.
      ([Pull Request](rails#29630))
  ```
  since it was backported to
  `5-1-stable` by c1014e4
  and
  `5-0-stable` by 0e71fc3.

- Remove
  ```
  *   Make `take_failed_screenshot` work within engine.
      ([Pull Request](rails#30421))
  ```
  since it was backported to
  `5-1-stable` by 595a231.

- Remove
  ```
  *   Fix optimized url helpers when using relative url root.
      ([Pull Request](rails#31261))
  ```
  since it was backported to
  `5-1-stable` by e9b7795.

- Remove
  ```
  *   Update `distance_of_time_in_words` helper to display better error messages
      for bad input.
      ([Pull Request](rails#20701))
  ```
  since it was backported to
  `5-1-stable` by 2c97fbf.

- Remove
  ```
  *   Generate field ids in `collection_check_boxes` and
      `collection_radio_buttons`.
      ([Pull Request](rails#29412))
  ```
  since it was backported to
  `5-1-stable` by 2d8c10a.

- Remove
  ```
  *   Fix issues with scopes and engine on `current_page?` method.
      ([Pull Request](rails#29503))
  ```
  since it was backported to
  `5-1-stable` by 2135daf.

- Remove
  ```
  *   Bring back proc with arity of 1 in `ActionMailer::Base.default` proc
      since it was supported in Rails 5.0 but not deprecated.
      ([Pull Request](rails#30391))
  ```
  since it was backported to
  `5-1-stable` by b2bedb1.

- Remove
  ```
  *   Add type caster to `RuntimeReflection#alias_name`.
      ([Pull Request](rails#28961))
  ```
  since it was backported to
  `5-1-stable` by f644e7a.

- Remove
  ```
  *   Loading model schema from database is now thread-safe.
      ([Pull Request](rails#29216))
  ```
  since it was backported to
  `5-1-stable` by 02926cf.
  and
  `5-0-stable` by 84bcfe5

- Remove
  ```
  *   Fix destroying existing object does not work well when optimistic locking
      enabled and `locking_column` is null in the database.
      ([Pull Request](rails#28926))
  ```
  since it was backported to
  `5-1-stable` by e498052.

- Remove
  ```
  *   `ActiveRecord::Persistence#touch` does not work well
      when optimistic locking enabled and `locking_column`,
      without default value, is null in the database.
      ([Pull Request](rails#28914))
  ```
  since it was backported to
  `5-1-stable` by 1e2f63d.

- Remove
  ```
  *   Previously, when building records using a `has_many :through` association,
      if the child records were deleted before the parent was saved,
      they would still be persisted. Now, if child records are deleted
      before the parent is saved on a `has_many :through` association,
      the child records will not be persisted.
      ([Pull Request](rails#29593))
  ```
  since it was backported to
  `5-1-stable` by a22c39e.

- Remove
  ```
  *   Query cache was unavailable when entering the `ActiveRecord::Base.cache`
      block without being connected.
      ([Pull Request](rails#29609))
  ```
  since it was backported to
  `5-1-stable` by fd6c8cd
  and
  `5-0-stable` by 9f2532b.

- Remove
  ```
  *   `Relation#joins` is no longer affected by the target model's
      `current_scope`, with the exception of `unscoped`.
      ([Commit](rails@5c71000))
  ```
  since it was backported to
  `5-1-stable` by 3630d63.

- Remove
  ```
  *   Fix `unscoped(where: [columns])` removing the wrong bind values.
      ([Pull Request](rails#29780))
  ```
  since it was backported to
  `5-1-stable` by d378fcb.

- Remove
  ```
  *   When a `has_one` association is destroyed by `dependent: destroy`,
      `destroyed_by_association` will now be set to the reflection, matching the
      behaviour of `has_many` associations.
      ([Pull Request](rails#29855))
  ```
  since it was backported to
  `5-1-stable` by 8254a8b.

- Remove
  ```
  *   Fix `COUNT(DISTINCT ...)` with `ORDER BY` and `LIMIT`
      to keep the existing select list.
      ([Pull Request](rails#29848))
  ```
  since it was backported to
  `5-1-stable` by 0e8d4ed.

- Remove
  ```
  *   Ensure `sum` honors `distinct` on `has_many :through` associations.
      ([Commit](rails@566f1fd))
  ```
  since it was backported to
  `5-1-stable` by c0a1dc2.

- Remove
  ```
  *   Fix `COUNT(DISTINCT ...)` for `GROUP BY` with `ORDER BY` and `LIMIT`.
      ([Commit](rails@5668dc6))
  ```
  since it was backported to
  `5-1-stable` by 87ca68e.

- Remove
  ```
  *   MySQL: Don't lose `auto_increment: true` in the `db/schema.rb`.
      ([Commit](rails@9493d45))
  ```
  since it was backported to
  `5-1-stable` by 8b6e694.

- Remove
  ```
  *   Fix longer sequence name detection for serial columns.
      ([Pull Request](rails#28339))
  ```
  since it was backported to
  `5-1-stable` by af9c170
  and
  `5-0-stable` by 7025b1d.

- Remove
  ```
  *   Fix `bin/rails db:setup` and `bin/rails db:test:prepare` create wrong
      ar_internal_metadata's data for a test database.
      ([Pull Request](rails#30579))
  ```
  since it was backported to
  `5-1-stable` by bb67b5f
  and
  `5-0-stable` by 60437e6.

- Remove
  ```
  *   Fix conflicts `counter_cache` with `touch: true` by optimistic locking.
      ([Pull Request](rails#31405))
  ```
  since it was backported to
  `5-1-stable` by 5236dda.

- Remove
  ```
  *   Fix `count(:all)` to correctly work `distinct` with custom SELECT list.
      ([Commit](rails@c6cd9a5))
  ```
  since it was backported to
  `5-1-stable` by 6beb4de.

- Remove
  ```
  *   Fix to invoke callbacks when using `update_attribute`.
      ([Commit](rails@732aa34))
  ```
  since it was backported to
  `5-1-stable` by 6346683.

- Remove
  ```
  *   Use `count(:all)` in `HasManyAssociation#count_records` to prevent invalid
      SQL queries for association counting.
      ([Pull Request](rails#27561))
  ```
  since it was backported to
  `5-1-stable` by eef3c89.

- Remove
  ```
  *   Fix `count(:all)` with eager loading and having an order other than
      the driving table.
      ([Commit](rails@ebc09ed))
  ```
  since it was backported to
  `5-1-stable` by 6df9b69.

- Remove
  ```
  *   PostgreSQL: Allow pg-1.0 gem to be used with Active Record.
      ([Pull Request](rails#31671))
  ```
  since it was backported to
  `5-1-stable` by a9c06f6.

- Remove
  ```
  *   Fix that after commit callbacks on update does not triggered
      when optimistic locking is enabled.
      ([Commit](rails@7f9bd03))
  ```
  since it was backported to
  `5-1-stable` by aaee10e.

- Remove
  ```
  *   Fix regression in numericality validator when comparing Decimal and Float
      input values with more scale than the schema.
      ([Pull Request](rails#28584))
  ```
  since it was backported to
  `5-1-stable` by 5b1c3e5.
  Note that there was incorrect link to PR,
  original PR is rails#29249.

- Remove
  ```
  *   Fix to working before/after validation callbacks on multiple contexts.
      ([Pull Request](rails#31483))
  ```
  since it was backported to
  `5-1-stable` by 0f7046a.

- Remove
  ```
  *   Fix implicit coercion calculations with scalars and durations.
      ([Pull Request](rails#29163),
      [Pull Request](rails#29971))
  ```
  since it was backported to
  `5-1-stable` by 51ea27c,
                  4d82e2a.

- Remove
  ```
  *   Fix modulo operations involving durations.
      ([Commit](rails@a54e13b))
  ```
  since it was backported to
  `5-1-stable` by 233fa7e.

- Remove
  ```
  *   Return all mappings for a timezone identifier in `country_zones`.
      ([Commit](rails@cdce6a7))
  ```
  since it was backported to
  `5-1-stable` by 0222ebb.

- Remove
  ```
  *   Add support for compatibility with redis-rb gem for 4.0 version.
      ([Pull Request](rails#30748))
  ```
  since it was backported to
  `5-1-stable` by 3789531.
  Related to rails#32252.

Related to rails#32222, rails#32222 (comment).
Follow up a489cc8.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants