Range and Date in Ruby on Rails
Tags: ruby, rails, tutorial, programming
Published: 2022-01-31 06:50:11

Ruby on Rails has its own extension of the Date class, making it very comfortable to work with dates.

No parsing, no conversion, we write our date helpers like a natural language, so we can read the code in fluent English and at times forget that we are dealing with a programming language. Today I'll show you how to use the combination of the Range and Date classes in Ruby on Rails to create a readable date check.

The specificity of Ruby allows for one more great thing - expanding core classes. In this example, we will extend the Date class provided by Ruby on Rails.

##Case:

In the offer of report modules or dashboards, you can meet operations consisting of comparing data, filtering data from the previous year, discussion or week. Working with dates in RoR is super fun anyway, but the snippet below will make it even more fun.

```ruby
class Date

  def is_in? range
    range.include? self
  end

  class << self
    def today
      Date.current
    end

    def previous_year
      today.prev_year.beginning_of_year..today.prev_year.end_of_year
    end

    def current_year
      today.beginning_of_year..today.end_of_year
    end

    def previous_month
      today.prev_month.beginning_of_month..today.prev_month.end_of_month
    end

    def current_month
      today.beginning_of_month..today.end_of_month
    end

    def previous_week
      today.prev_week.beginning_of_week..today.prev_week.end_of_week
    end

    def current_week
      today.beginning_of_week..today.end_of_week
    end
  end

end
```

We extend `the Date` class here.

First, I declare an instance method that will check if the date is within the given range. This is an instance method, which will call for instance, or in simpler terms - directly on the date.

```ruby
def is_in? range
  range.include? self
end
```

Then extend `the Date` class with static methods. I am overwriting `today` method.

```ruby
def today
  Date.current
end
```

I create a `previous_year` method using a Range that returns a date range for the previous year.

```ruby
def previous_year
  today.prev_year.beginning_of_year..today.prev_year.end_of_year
end
```

Next, I create a `current_year` method that returns a date range for the current year.

```ruby
def current_year
    today.beginning_of_year..today.end_of_year
  end
```

Next, the `previous_month`, `current_month`, `previous_week`, and `current_week` methods.

```ruby
def previous_month
  today.prev_month.beginning_of_month..today.prev_month.end_of_month
end
```

```ruby
def current_month
  today.beginning_of_month..today.end_of_month
end
```

```ruby
def previous_week
  today.prev_week.beginning_of_week..today.prev_week.end_of_week
end
```

```ruby
def current_week
  today.beginning_of_week..today.end_of_week
end
```

After creating these auxiliary methods, we can easily write date checking conditions.

```ruby
Date.today.is_in?(Date.current_week)

invoice.date.is_in?(Date.previous_year)

Date.current_week.include?(report.date)
```

Combining the `Range` and `Date` classes in Ruby on Rails is a good idea to improve the readability of your code.

In the documentation, you can read about [the Range class](https://ruby-doc.org/core-2.7.1/Range.html) and [the Date class](https://api.rubyonrails.org/classes/Date.html).