DEV Community

Jeremy
Jeremy

Posted on

Use Ruby Range with date objects

It is quite common to need to define time periods in your application, most often it is modeled by a start date and an end date. Then these dates are compared to the current date for thing like knowing if a customer is a paying member.

This way of doing often results in methods that could be hard to read

class User
  def paying_member?
    subscription_started_at <= Date.current &&
      (subscription_ended_at.nil? || subscription_ended_at > Date.current)
  end
end
Enter fullscreen mode Exit fullscreen mode

But there is a way to improve the readability of your code using the Ruby’s Range class.

class User
  def paying_member?
    subscription_period.cover?(Date.current)
  end

  private

  def subscription_period
    subscription_started_at..subscription_ended_at
  end
end
Enter fullscreen mode Exit fullscreen mode

In the event that the customer do not have terminated its subscription the subscription_period will return an infinite Range which will also validate our predicate.

Now let’s say that business consider that the subscription is supposed to be over the day before its stored end date, it is quite simple to modify the subscription_period method to return a Range that exclude its upper limit.

class User
  # ...
  def subscription_period
    subscription_started_at...subscription_ended_at
  end
end
Enter fullscreen mode Exit fullscreen mode

In a Rails application, it is also possible to take advantage of the methods Range#=== and Range#overlaps? added to the Range class by ActiveSupport.

class User
  def subscriber_kind
    case subscription_period
    when innovator_period then 'Innovator'
    when early_adopter_period then 'Early adopter'
    when early_majority_period then 'Early majority'
    when late_majority_period then 'Late majority'
    when laggards_period then 'Laggard'
  end

  def share_subscription_with(user)
    subscription_period.overlaps?(user.subscription_period)
  end
end
Enter fullscreen mode Exit fullscreen mode

Links

Top comments (0)