33module RuboCop
44 module Cop
55 module Rails
6- # Checks that Rails.env is compared using `.production?`-like
6+ # Checks that ` Rails.env` is compared using `.production?`-like
77 # methods instead of equality against a string or symbol.
88 #
99 # @example
1010 # # bad
1111 # Rails.env == 'production'
12+ # Rails.env.to_sym == :production
1213 #
1314 # # bad, always returns false
1415 # Rails.env == :test
@@ -18,26 +19,40 @@ module Rails
1819 class EnvironmentComparison < Base
1920 extend AutoCorrector
2021
21- MSG = 'Favor `%<bang>sRails.env.%<env>s? ` over `%<source>s`.'
22+ MSG = 'Favor `%<prefer>s ` over `%<source>s`.'
2223
2324 SYM_MSG = 'Do not compare `Rails.env` with a symbol, it will always evaluate to `false`.'
2425
2526 RESTRICT_ON_SEND = %i[ == != ] . freeze
2627
27- def_node_matcher :comparing_str_env_with_rails_env_on_lhs? , <<~PATTERN
28- (send
29- (send (const {nil? cbase} :Rails) :env)
30- {:== :!=}
31- $str
32- )
28+ def_node_matcher :comparing_env_with_rails_env_on_lhs? , <<~PATTERN
29+ {
30+ (send
31+ (send (const {nil? cbase} :Rails) :env)
32+ {:== :!=}
33+ $str
34+ )
35+ (send
36+ (send (send (const {nil? cbase} :Rails) :env) :to_sym)
37+ {:== :!=}
38+ $sym
39+ )
40+ }
3341 PATTERN
3442
35- def_node_matcher :comparing_str_env_with_rails_env_on_rhs? , <<~PATTERN
36- (send
37- $str
38- {:== :!=}
39- (send (const {nil? cbase} :Rails) :env)
40- )
43+ def_node_matcher :comparing_env_with_rails_env_on_rhs? , <<~PATTERN
44+ {
45+ (send
46+ $str
47+ {:== :!=}
48+ (send (const {nil? cbase} :Rails) :env)
49+ )
50+ (send
51+ $sym
52+ {:== :!=}
53+ (send (send (const {nil? cbase} :Rails) :env) :to_sym)
54+ )
55+ }
4156 PATTERN
4257
4358 def_node_matcher :comparing_sym_env_with_rails_env_on_lhs? , <<~PATTERN
@@ -56,59 +71,52 @@ class EnvironmentComparison < Base
5671 )
5772 PATTERN
5873
59- def_node_matcher :content , <<~PATTERN
60- ({str sym} $_)
61- PATTERN
62-
6374 def on_send ( node )
64- if ( env_node = comparing_str_env_with_rails_env_on_lhs? ( node ) ||
65- comparing_str_env_with_rails_env_on_rhs? ( node ) )
66- env , = *env_node
67- bang = node . method? ( :!= ) ? '!' : ''
68- message = format ( MSG , bang : bang , env : env , source : node . source )
69-
70- add_offense ( node , message : message ) do |corrector |
71- autocorrect ( corrector , node )
72- end
75+ check_env_comparison_with_rails_env ( node )
76+ check_sym_env_comparison_with_rails_env ( node )
77+ end
78+
79+ private
80+
81+ def check_env_comparison_with_rails_env ( node )
82+ return unless comparing_env_with_rails_env_on_lhs? ( node ) || comparing_env_with_rails_env_on_rhs? ( node )
83+
84+ replacement = build_predicate_method ( node )
85+ message = format ( MSG , prefer : replacement , source : node . source )
86+
87+ add_offense ( node , message : message ) do |corrector |
88+ corrector . replace ( node , replacement )
7389 end
90+ end
7491
92+ def check_sym_env_comparison_with_rails_env ( node )
7593 return unless comparing_sym_env_with_rails_env_on_lhs? ( node ) || comparing_sym_env_with_rails_env_on_rhs? ( node )
7694
7795 add_offense ( node , message : SYM_MSG ) do |corrector |
78- autocorrect ( corrector , node )
96+ replacement = build_predicate_method ( node )
97+ corrector . replace ( node , replacement )
7998 end
8099 end
81100
82- private
101+ def build_predicate_method ( node )
102+ bang = node . method? ( :!= ) ? '!' : ''
83103
84- def autocorrect ( corrector , node )
85- replacement = build_predicate_method ( node )
104+ receiver , argument = extract_receiver_and_argument ( node )
105+ receiver = receiver . receiver if receiver . method? ( :to_sym )
86106
87- corrector . replace ( node , replacement )
107+ " #{ bang } #{ receiver . source } . #{ argument . value } ?"
88108 end
89109
90- def build_predicate_method ( node )
110+ def extract_receiver_and_argument ( node )
91111 if rails_env_on_lhs? ( node )
92- build_predicate_method_for_rails_env_on_lhs ( node )
112+ [ node . receiver , node . first_argument ]
93113 else
94- build_predicate_method_for_rails_env_on_rhs ( node )
114+ [ node . first_argument , node . receiver ]
95115 end
96116 end
97117
98118 def rails_env_on_lhs? ( node )
99- comparing_str_env_with_rails_env_on_lhs? ( node ) || comparing_sym_env_with_rails_env_on_lhs? ( node )
100- end
101-
102- def build_predicate_method_for_rails_env_on_lhs ( node )
103- bang = node . method? ( :!= ) ? '!' : ''
104-
105- "#{ bang } #{ node . receiver . source } .#{ content ( node . first_argument ) } ?"
106- end
107-
108- def build_predicate_method_for_rails_env_on_rhs ( node )
109- bang = node . method? ( :!= ) ? '!' : ''
110-
111- "#{ bang } #{ node . first_argument . source } .#{ content ( node . receiver ) } ?"
119+ comparing_env_with_rails_env_on_lhs? ( node ) || comparing_sym_env_with_rails_env_on_lhs? ( node )
112120 end
113121 end
114122 end
0 commit comments