Skip to content

Commit

Permalink
Make Rails/ExpandedDateRange aware beginning_of_week with an argu…
Browse files Browse the repository at this point in the history
…ment

This PR makes `Rails/ExpandedDateRange` aware `beginning_of_week` with an argument.

```ruby
# bad
date.beginning_of_week(:sunday)..date.end_of_week(:sunday)

# good
date.all_week(:sunday)
```
  • Loading branch information
koic committed Jun 30, 2022
1 parent 0c18551 commit 15858ae
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#737](https://github.com/rubocop/rubocop-rails/pull/737): Make `Rails/ExpandedDateRange` aware `beginning_of_week` with an argument. ([@koic][])
60 changes: 38 additions & 22 deletions lib/rubocop/cop/rails/expanded_date_range.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,6 @@ class ExpandedDateRange < Base

minimum_target_rails_version 5.1

def_node_matcher :expanded_date_range, <<~PATTERN
(irange
(send
$_ {:beginning_of_day :beginning_of_week :beginning_of_month :beginning_of_quarter :beginning_of_year})
(send
$_ {:end_of_day :end_of_week :end_of_month :end_of_quarter :end_of_year}))
PATTERN

PREFERRED_METHODS = {
beginning_of_day: 'all_day',
beginning_of_week: 'all_week',
Expand All @@ -54,31 +46,55 @@ class ExpandedDateRange < Base
}.freeze

def on_irange(node)
return unless expanded_date_range(node)

begin_node = node.begin
end_node = node.end
return unless same_receiver?(begin_node, end_node)

beginning_method = begin_node.method_name
end_method = end_node.method_name
return unless use_mapped_methods?(beginning_method, end_method)
return if allow?(begin_node, end_node)

preferred_method = "#{begin_node.receiver.source}.#{PREFERRED_METHODS[beginning_method]}"
preferred_method = preferred_method(begin_node)
if begin_node.method?(:beginning_of_week) && begin_node.arguments.one?
return unless same_argument?(begin_node, end_node)

add_offense(node, message: format(MSG, preferred_method: preferred_method)) do |corrector|
corrector.replace(node, preferred_method)
preferred_method << "(#{begin_node.first_argument.source})"
elsif any_arguments?(begin_node, end_node)
return
end

register_offense(node, preferred_method)
end

private

def same_receiver?(begin_node, end_node)
begin_node.receiver.source == end_node.receiver.source
def allow?(begin_node, end_node)
return true unless (begin_source = receiver_source(begin_node))
return true unless (end_source = receiver_source(end_node))

begin_source != end_source || MAPPED_DATE_RANGE_METHODS[begin_node.method_name] != end_node.method_name
end

def receiver_source(node)
return if !node&.send_type? || node.receiver.nil?

node.receiver.source
end

def use_mapped_methods?(beginning_method, end_method)
MAPPED_DATE_RANGE_METHODS[beginning_method] == end_method
def same_argument?(begin_node, end_node)
begin_node.first_argument.source == end_node.first_argument.source
end

def preferred_method(begin_node)
+"#{begin_node.receiver.source}.#{PREFERRED_METHODS[begin_node.method_name]}"
end

def any_arguments?(begin_node, end_node)
begin_node.arguments.any? || end_node.arguments.any?
end

def register_offense(node, preferred_method)
message = format(MSG, preferred_method: preferred_method)

add_offense(node, message: message) do |corrector|
corrector.replace(node, preferred_method)
end
end
end
end
Expand Down
41 changes: 41 additions & 0 deletions spec/rubocop/cop/rails/expanded_date_range_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@
RUBY
end

it 'registers and corrects an offense when using `date.beginning_of_week(:sunday)..date.end_of_week(:sunday)`' do
expect_offense(<<~RUBY)
date.beginning_of_week(:sunday)..date.end_of_week(:sunday)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `date.all_week(:sunday)` instead.
RUBY

expect_correction(<<~RUBY)
date.all_week(:sunday)
RUBY
end

it 'registers and corrects an offense when using `date.beginning_of_year..date.end_of_year`' do
expect_offense(<<~RUBY)
date.beginning_of_year..date.end_of_year
Expand Down Expand Up @@ -110,6 +121,36 @@
date.beginning_of_day..date.end_of_year
RUBY
end

it 'does not register an offense when `date.beginning_of_week(:sunday)..date.end_of_week(:saturday)`' do
expect_no_offenses(<<~RUBY)
date.beginning_of_week(:sunday)..date.end_of_week(:saturday)
RUBY
end

it 'does not register an offense when `date.beginning_of_day..date.end_of_day` with any argument' do
expect_no_offenses(<<~RUBY)
date.beginning_of_day(arg)..date.end_of_day(arg)
RUBY
end

it 'does not register an offense when `beginning_of_day..end_of_day`' do
expect_no_offenses(<<~RUBY)
beginning_of_day..end_of_day
RUBY
end

it 'does not register an offense when `beginning_of_day..date.end_of_day`' do
expect_no_offenses(<<~RUBY)
beginning_of_day..date.end_of_day
RUBY
end

it 'does not register an offense when `date.beginning_of_day..end_of_day`' do
expect_no_offenses(<<~RUBY)
date.beginning_of_day..end_of_day
RUBY
end
end

context 'Rails <= 5.0', :rails50 do
Expand Down

0 comments on commit 15858ae

Please sign in to comment.