Add Duration#before and #after as aliases for #ago and #since - #27721
Add Duration#before and #after as aliases for #ago and #since#27721Widdershin wants to merge 2 commits into
Conversation
|
cc @pixeltrix |
|
For comparison, the existing API: let(:today) { 2.weeks.since(customer_start_date) }
let(:earlier_date) { 5.days.until(today) } |
|
I think the consensus is that existing methods are fine and adding new aliases isn't required. @Widdershin sorry, but thanks for your suggestion. |
|
I'm quite sympathetic to this. If you gave me the choice between: let(:today) { 2.weeks.since(customer_start_date) }
let(:earlier_date) { 5.days.until(today) }And let(:today) { 2.weeks.after(customer_start_date) }
let(:earlier_date) { 5.days.before(today) }I'd say the latter requires far less mental gymnastics to read. And I think that's a good example of the strength of alias. It allows us to bend the same instructions to read the most natural in more instances. |
|
Actually, I think the after is compelling enough that I'd like to see this make it in. I'd want to write code like the latter. |
|
Need a CHANGELOG entry explaining its value. Do use the before/after example. |
|
@dhh Thanks for your consideration. I've altered my commit to include a CHANGELOG entry. Let me know if you want anything else added. |
There was a problem hiding this comment.
This is a good example, but it suggests that the API is somehow related to specs or that its value is derived from an edge case usage.
Think a simple before/after with just the code is clear & convincing, e.g.
Add `ActiveSupport::Duration#before` and `#after` as aliases for `#until` and `#since`
These read more like English and require less mental gymnastics to read and write.
Before:
2.weeks.since(customer_start_date)
5.days.until(today)
After:
2.weeks.after(customer_start_date)
5.days.before(today)
There was a problem hiding this comment.
Still feels weird to alias these—and leave ago's required argument as optional—rather than define new methods. Not necessary for this PR, but worth considering
# Calculates this duration in the past relative to +date_or_time+.
def before(date_or_time)
sum(-1, date_or_time)
end
alias :until :before
def ago
before ::Time.current
endThat'd break people using the odd 2.days.ago customer_start_date and 5.weeks.since formulations, though, so it'd need deprecation 😐
There was a problem hiding this comment.
I'm happy to make this change if it's desired, but as you say, perhaps in a different PR. What is the process for deprecating something like that?
There was a problem hiding this comment.
The process is to allow both old and new method signatures and give a deprecation warning if we see the old one.
# Calculates this duration in the past relative to +date_or_time+.
def before(date_or_time)
sum(-1, date_or_time)
end
alias :until :before
def ago(deprecated_date_or_time = nil)
if deprecated_date_or_time
ActiveSupport::Deprecation.warn "Passing a date_or_time argument to #ago is deprecated and will be removed in Rails 5.2. Use #before(date_or_time) instead."
end
before deprecated_date_or_time || ::Time.current
end|
I have resolved the conflicts and updated the CHANGELOG entry as per @jeremy's feedback. Please let me know if there's anything else you would like done before this is merged. |
jeremy
left a comment
There was a problem hiding this comment.
Needs test coverage for the new aliases. (If these were removed, no tests would fail, but apps would break.)
|
Hi @jeremy, thanks for your review. I have added test coverage. I included a test for calling before and after with no arguments, following the rationale that since it's part of the public API it should be tested to avoid regressions. I did not duplicate the more intricate test coverage for since and ago, but I can if desired. I also removed the comma from my changelog entry. Please let me know if there are any other changes desired. 😸 |
It's common in test cases at my job to have code like this:
let(:today) { customer_start_date + 2.weeks }
let(:earlier_date) { today - 5.days }
With this change, we can instead write
let(:today) { 2.weeks.after(customer_start_date) }
let(:earlier_date) { 5.days.before(today) }
|
Looks like I have a failure to look into. Strange, as I've adapted that test directly from another one. |
|
Thanks @jeremy for your review and merge, and also for sorting out that test case for me. 😄 |
It's common in test cases at my job to have code like this:
With this change, we can instead write:
I find this to be much more readable, and it makes me happy 😄
A small downside I see is that
beforeandafterdon't make very much sense when used without an argument.I would be happy to pull these into a new set of methods that always take an argument, but I figured that the lowest impact change was an alias.
I also did not add a test case, as I saw there was no additional test coverage for
sinceandago. If desired I will happily add a test case.Please let me know if there's anything else I can address. Additionally, if this change isn't desired, please feel free to close it.