Skip to content

Commit 15858ae

Browse files
committed
Make Rails/ExpandedDateRange aware beginning_of_week with an argument
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) ```
1 parent 0c18551 commit 15858ae

File tree

3 files changed

+80
-22
lines changed

3 files changed

+80
-22
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#737](https://github.com/rubocop/rubocop-rails/pull/737): Make `Rails/ExpandedDateRange` aware `beginning_of_week` with an argument. ([@koic][])

lib/rubocop/cop/rails/expanded_date_range.rb

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,6 @@ class ExpandedDateRange < Base
2929

3030
minimum_target_rails_version 5.1
3131

32-
def_node_matcher :expanded_date_range, <<~PATTERN
33-
(irange
34-
(send
35-
$_ {:beginning_of_day :beginning_of_week :beginning_of_month :beginning_of_quarter :beginning_of_year})
36-
(send
37-
$_ {:end_of_day :end_of_week :end_of_month :end_of_quarter :end_of_year}))
38-
PATTERN
39-
4032
PREFERRED_METHODS = {
4133
beginning_of_day: 'all_day',
4234
beginning_of_week: 'all_week',
@@ -54,31 +46,55 @@ class ExpandedDateRange < Base
5446
}.freeze
5547

5648
def on_irange(node)
57-
return unless expanded_date_range(node)
58-
5949
begin_node = node.begin
6050
end_node = node.end
61-
return unless same_receiver?(begin_node, end_node)
62-
63-
beginning_method = begin_node.method_name
64-
end_method = end_node.method_name
65-
return unless use_mapped_methods?(beginning_method, end_method)
51+
return if allow?(begin_node, end_node)
6652

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

69-
add_offense(node, message: format(MSG, preferred_method: preferred_method)) do |corrector|
70-
corrector.replace(node, preferred_method)
57+
preferred_method << "(#{begin_node.first_argument.source})"
58+
elsif any_arguments?(begin_node, end_node)
59+
return
7160
end
61+
62+
register_offense(node, preferred_method)
7263
end
7364

7465
private
7566

76-
def same_receiver?(begin_node, end_node)
77-
begin_node.receiver.source == end_node.receiver.source
67+
def allow?(begin_node, end_node)
68+
return true unless (begin_source = receiver_source(begin_node))
69+
return true unless (end_source = receiver_source(end_node))
70+
71+
begin_source != end_source || MAPPED_DATE_RANGE_METHODS[begin_node.method_name] != end_node.method_name
72+
end
73+
74+
def receiver_source(node)
75+
return if !node&.send_type? || node.receiver.nil?
76+
77+
node.receiver.source
7878
end
7979

80-
def use_mapped_methods?(beginning_method, end_method)
81-
MAPPED_DATE_RANGE_METHODS[beginning_method] == end_method
80+
def same_argument?(begin_node, end_node)
81+
begin_node.first_argument.source == end_node.first_argument.source
82+
end
83+
84+
def preferred_method(begin_node)
85+
+"#{begin_node.receiver.source}.#{PREFERRED_METHODS[begin_node.method_name]}"
86+
end
87+
88+
def any_arguments?(begin_node, end_node)
89+
begin_node.arguments.any? || end_node.arguments.any?
90+
end
91+
92+
def register_offense(node, preferred_method)
93+
message = format(MSG, preferred_method: preferred_method)
94+
95+
add_offense(node, message: message) do |corrector|
96+
corrector.replace(node, preferred_method)
97+
end
8298
end
8399
end
84100
end

spec/rubocop/cop/rails/expanded_date_range_spec.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@
4646
RUBY
4747
end
4848

49+
it 'registers and corrects an offense when using `date.beginning_of_week(:sunday)..date.end_of_week(:sunday)`' do
50+
expect_offense(<<~RUBY)
51+
date.beginning_of_week(:sunday)..date.end_of_week(:sunday)
52+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `date.all_week(:sunday)` instead.
53+
RUBY
54+
55+
expect_correction(<<~RUBY)
56+
date.all_week(:sunday)
57+
RUBY
58+
end
59+
4960
it 'registers and corrects an offense when using `date.beginning_of_year..date.end_of_year`' do
5061
expect_offense(<<~RUBY)
5162
date.beginning_of_year..date.end_of_year
@@ -110,6 +121,36 @@
110121
date.beginning_of_day..date.end_of_year
111122
RUBY
112123
end
124+
125+
it 'does not register an offense when `date.beginning_of_week(:sunday)..date.end_of_week(:saturday)`' do
126+
expect_no_offenses(<<~RUBY)
127+
date.beginning_of_week(:sunday)..date.end_of_week(:saturday)
128+
RUBY
129+
end
130+
131+
it 'does not register an offense when `date.beginning_of_day..date.end_of_day` with any argument' do
132+
expect_no_offenses(<<~RUBY)
133+
date.beginning_of_day(arg)..date.end_of_day(arg)
134+
RUBY
135+
end
136+
137+
it 'does not register an offense when `beginning_of_day..end_of_day`' do
138+
expect_no_offenses(<<~RUBY)
139+
beginning_of_day..end_of_day
140+
RUBY
141+
end
142+
143+
it 'does not register an offense when `beginning_of_day..date.end_of_day`' do
144+
expect_no_offenses(<<~RUBY)
145+
beginning_of_day..date.end_of_day
146+
RUBY
147+
end
148+
149+
it 'does not register an offense when `date.beginning_of_day..end_of_day`' do
150+
expect_no_offenses(<<~RUBY)
151+
date.beginning_of_day..end_of_day
152+
RUBY
153+
end
113154
end
114155

115156
context 'Rails <= 5.0', :rails50 do

0 commit comments

Comments
 (0)