rubocop-rails 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +73 -0
- data/bin/setup +7 -0
- data/config/default.yml +466 -0
- data/lib/rubocop-rails.rb +12 -0
- data/lib/rubocop/cop/mixin/target_rails_version.rb +16 -0
- data/lib/rubocop/cop/rails/action_filter.rb +117 -0
- data/lib/rubocop/cop/rails/active_record_aliases.rb +48 -0
- data/lib/rubocop/cop/rails/active_record_override.rb +82 -0
- data/lib/rubocop/cop/rails/active_support_aliases.rb +69 -0
- data/lib/rubocop/cop/rails/application_job.rb +40 -0
- data/lib/rubocop/cop/rails/application_record.rb +40 -0
- data/lib/rubocop/cop/rails/assert_not.rb +44 -0
- data/lib/rubocop/cop/rails/belongs_to.rb +102 -0
- data/lib/rubocop/cop/rails/blank.rb +164 -0
- data/lib/rubocop/cop/rails/bulk_change_table.rb +289 -0
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +91 -0
- data/lib/rubocop/cop/rails/date.rb +161 -0
- data/lib/rubocop/cop/rails/delegate.rb +132 -0
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +37 -0
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +91 -0
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +45 -0
- data/lib/rubocop/cop/rails/environment_comparison.rb +68 -0
- data/lib/rubocop/cop/rails/exit.rb +67 -0
- data/lib/rubocop/cop/rails/file_path.rb +108 -0
- data/lib/rubocop/cop/rails/find_by.rb +55 -0
- data/lib/rubocop/cop/rails/find_each.rb +51 -0
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +25 -0
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +106 -0
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +39 -0
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +117 -0
- data/lib/rubocop/cop/rails/http_status.rb +160 -0
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +94 -0
- data/lib/rubocop/cop/rails/inverse_of.rb +246 -0
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +175 -0
- data/lib/rubocop/cop/rails/link_to_blank.rb +98 -0
- data/lib/rubocop/cop/rails/not_null_column.rb +67 -0
- data/lib/rubocop/cop/rails/output.rb +49 -0
- data/lib/rubocop/cop/rails/output_safety.rb +99 -0
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +107 -0
- data/lib/rubocop/cop/rails/presence.rb +124 -0
- data/lib/rubocop/cop/rails/present.rb +153 -0
- data/lib/rubocop/cop/rails/read_write_attribute.rb +74 -0
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +111 -0
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +136 -0
- data/lib/rubocop/cop/rails/reflection_class_name.rb +37 -0
- data/lib/rubocop/cop/rails/refute_methods.rb +76 -0
- data/lib/rubocop/cop/rails/relative_date_constant.rb +93 -0
- data/lib/rubocop/cop/rails/request_referer.rb +56 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +286 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +87 -0
- data/lib/rubocop/cop/rails/save_bang.rb +316 -0
- data/lib/rubocop/cop/rails/scope_args.rb +29 -0
- data/lib/rubocop/cop/rails/skips_model_validations.rb +87 -0
- data/lib/rubocop/cop/rails/time_zone.rb +238 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +105 -0
- data/lib/rubocop/cop/rails/unknown_env.rb +63 -0
- data/lib/rubocop/cop/rails/validation.rb +109 -0
- data/lib/rubocop/cop/rails_cops.rb +64 -0
- data/lib/rubocop/rails.rb +12 -0
- data/lib/rubocop/rails/inject.rb +18 -0
- data/lib/rubocop/rails/version.rb +10 -0
- metadata +143 -0
@@ -0,0 +1,175 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks that methods specified in the filter's `only` or
|
7
|
+
# `except` options are defined within the same class or module.
|
8
|
+
#
|
9
|
+
# You can technically specify methods of superclass or methods added by
|
10
|
+
# mixins on the filter, but these can confuse developers. If you specify
|
11
|
+
# methods that are defined in other classes or modules, you should
|
12
|
+
# define the filter in that class or module.
|
13
|
+
#
|
14
|
+
# If you rely on behaviour defined in the superclass actions, you must
|
15
|
+
# remember to invoke `super` in the subclass actions.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# # bad
|
19
|
+
# class LoginController < ApplicationController
|
20
|
+
# before_action :require_login, only: %i[index settings logout]
|
21
|
+
#
|
22
|
+
# def index
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# class LoginController < ApplicationController
|
28
|
+
# before_action :require_login, only: %i[index settings logout]
|
29
|
+
#
|
30
|
+
# def index
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# def settings
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# def logout
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# # bad
|
42
|
+
# module FooMixin
|
43
|
+
# extend ActiveSupport::Concern
|
44
|
+
#
|
45
|
+
# included do
|
46
|
+
# before_action proc { authenticate }, only: :foo
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# # good
|
51
|
+
# module FooMixin
|
52
|
+
# extend ActiveSupport::Concern
|
53
|
+
#
|
54
|
+
# included do
|
55
|
+
# before_action proc { authenticate }, only: :foo
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# def foo
|
59
|
+
# # something
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
# class ContentController < ApplicationController
|
65
|
+
# def update
|
66
|
+
# @content.update(content_attributes)
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# class ArticlesController < ContentController
|
71
|
+
# before_action :load_article, only: [:update]
|
72
|
+
#
|
73
|
+
# # the cop requires this method, but it relies on behaviour defined
|
74
|
+
# # in the superclass, so needs to invoke `super`
|
75
|
+
# def update
|
76
|
+
# super
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# private
|
80
|
+
#
|
81
|
+
# def load_article
|
82
|
+
# @content = Article.find(params[:article_id])
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
class LexicallyScopedActionFilter < Cop
|
86
|
+
MSG = '%<action>s not explicitly defined on the %<type>s.'
|
87
|
+
|
88
|
+
FILTERS = %w[
|
89
|
+
:after_action
|
90
|
+
:append_after_action
|
91
|
+
:append_around_action
|
92
|
+
:append_before_action
|
93
|
+
:around_action
|
94
|
+
:before_action
|
95
|
+
:prepend_after_action
|
96
|
+
:prepend_around_action
|
97
|
+
:prepend_before_action
|
98
|
+
:skip_after_action
|
99
|
+
:skip_around_action
|
100
|
+
:skip_before_action
|
101
|
+
:skip_action_callback
|
102
|
+
].freeze
|
103
|
+
|
104
|
+
def_node_matcher :only_or_except_filter_methods, <<-PATTERN
|
105
|
+
(send
|
106
|
+
nil?
|
107
|
+
{#{FILTERS.join(' ')}}
|
108
|
+
_
|
109
|
+
(hash
|
110
|
+
(pair
|
111
|
+
(sym {:only :except})
|
112
|
+
$_)))
|
113
|
+
PATTERN
|
114
|
+
|
115
|
+
def on_send(node)
|
116
|
+
methods_node = only_or_except_filter_methods(node)
|
117
|
+
return unless methods_node
|
118
|
+
|
119
|
+
parent = node.each_ancestor(:class, :module).first
|
120
|
+
return unless parent
|
121
|
+
|
122
|
+
block = parent.each_child_node(:begin).first
|
123
|
+
return unless block
|
124
|
+
|
125
|
+
defined_methods = block.each_child_node(:def).map(&:method_name)
|
126
|
+
methods = array_values(methods_node).reject do |method|
|
127
|
+
defined_methods.include?(method)
|
128
|
+
end
|
129
|
+
|
130
|
+
message = message(methods, parent)
|
131
|
+
add_offense(node, message: message) unless methods.empty?
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
# @param node [RuboCop::AST::Node]
|
137
|
+
# @return [Array<Symbol>]
|
138
|
+
def array_values(node) # rubocop:disable Metrics/MethodLength
|
139
|
+
case node.type
|
140
|
+
when :str
|
141
|
+
[node.str_content.to_sym]
|
142
|
+
when :sym
|
143
|
+
[node.value]
|
144
|
+
when :array
|
145
|
+
node.values.map do |v|
|
146
|
+
case v.type
|
147
|
+
when :str
|
148
|
+
v.str_content.to_sym
|
149
|
+
when :sym
|
150
|
+
v.value
|
151
|
+
end
|
152
|
+
end.compact
|
153
|
+
else
|
154
|
+
[]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# @param methods [Array<String>]
|
159
|
+
# @param parent [RuboCop::AST::Node]
|
160
|
+
# @return [String]
|
161
|
+
def message(methods, parent)
|
162
|
+
if methods.size == 1
|
163
|
+
format(MSG,
|
164
|
+
action: "`#{methods[0]}` is",
|
165
|
+
type: parent.type)
|
166
|
+
else
|
167
|
+
format(MSG,
|
168
|
+
action: "`#{methods.join('`, `')}` are",
|
169
|
+
type: parent.type)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks for calls to `link_to` that contain a
|
7
|
+
# `target: '_blank'` but no `rel: 'noopener'`. This can be a security
|
8
|
+
# risk as the loaded page will have control over the previous page
|
9
|
+
# and could change its location for phishing purposes.
|
10
|
+
#
|
11
|
+
# The option `rel: 'noreferrer'` also blocks this behavior
|
12
|
+
# and removes the http-referrer header.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# # bad
|
16
|
+
# link_to 'Click here', url, target: '_blank'
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# link_to 'Click here', url, target: '_blank', rel: 'noopener'
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# link_to 'Click here', url, target: '_blank', rel: 'noreferrer'
|
23
|
+
class LinkToBlank < Cop
|
24
|
+
MSG = 'Specify a `:rel` option containing noopener.'
|
25
|
+
|
26
|
+
def_node_matcher :blank_target?, <<-PATTERN
|
27
|
+
(pair {(sym :target) (str "target")} {(str "_blank") (sym :_blank)})
|
28
|
+
PATTERN
|
29
|
+
|
30
|
+
def_node_matcher :includes_noopener?, <<-PATTERN
|
31
|
+
(pair {(sym :rel) (str "rel")} ({str sym} #contains_noopener?))
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def_node_matcher :rel_node?, <<-PATTERN
|
35
|
+
(pair {(sym :rel) (str "rel")} (str _))
|
36
|
+
PATTERN
|
37
|
+
|
38
|
+
def on_send(node)
|
39
|
+
return unless node.method?(:link_to)
|
40
|
+
|
41
|
+
option_nodes = node.each_child_node(:hash)
|
42
|
+
|
43
|
+
option_nodes.map(&:children).each do |options|
|
44
|
+
blank = options.find { |o| blank_target?(o) }
|
45
|
+
if blank && options.none? { |o| includes_noopener?(o) }
|
46
|
+
add_offense(blank)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def autocorrect(node)
|
52
|
+
lambda do |corrector|
|
53
|
+
send_node = node.parent.parent
|
54
|
+
|
55
|
+
option_nodes = send_node.each_child_node(:hash)
|
56
|
+
rel_node = nil
|
57
|
+
option_nodes.map(&:children).each do |options|
|
58
|
+
rel_node ||= options.find { |o| rel_node?(o) }
|
59
|
+
end
|
60
|
+
|
61
|
+
if rel_node
|
62
|
+
append_to_rel(rel_node, corrector)
|
63
|
+
else
|
64
|
+
add_rel(send_node, node, corrector)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def append_to_rel(rel_node, corrector)
|
72
|
+
existing_rel = rel_node.children.last.value
|
73
|
+
str_range = rel_node.children.last.loc.expression.adjust(
|
74
|
+
begin_pos: 1,
|
75
|
+
end_pos: -1
|
76
|
+
)
|
77
|
+
corrector.replace(str_range, "#{existing_rel} noopener")
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_rel(send_node, offence_node, corrector)
|
81
|
+
opening_quote = offence_node.children.last.source[0]
|
82
|
+
closing_quote = opening_quote == ':' ? '' : opening_quote
|
83
|
+
new_rel_exp = ", rel: #{opening_quote}noopener#{closing_quote}"
|
84
|
+
range = send_node.arguments.last.source_range
|
85
|
+
|
86
|
+
corrector.insert_after(range, new_rel_exp)
|
87
|
+
end
|
88
|
+
|
89
|
+
def contains_noopener?(value)
|
90
|
+
return false unless value
|
91
|
+
|
92
|
+
rel_array = value.to_s.split(' ')
|
93
|
+
rel_array.include?('noopener') || rel_array.include?('noreferrer')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks for add_column call with NOT NULL constraint
|
7
|
+
# in migration file.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# add_column :users, :name, :string, null: false
|
12
|
+
# add_reference :products, :category, null: false
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# add_column :users, :name, :string, null: true
|
16
|
+
# add_column :users, :name, :string, null: false, default: ''
|
17
|
+
# add_reference :products, :category
|
18
|
+
# add_reference :products, :category, null: false, default: 1
|
19
|
+
class NotNullColumn < Cop
|
20
|
+
MSG = 'Do not add a NOT NULL column without a default value.'
|
21
|
+
|
22
|
+
def_node_matcher :add_not_null_column?, <<-PATTERN
|
23
|
+
(send nil? :add_column _ _ _ (hash $...))
|
24
|
+
PATTERN
|
25
|
+
|
26
|
+
def_node_matcher :add_not_null_reference?, <<-PATTERN
|
27
|
+
(send nil? :add_reference _ _ (hash $...))
|
28
|
+
PATTERN
|
29
|
+
|
30
|
+
def_node_matcher :null_false?, <<-PATTERN
|
31
|
+
(pair (sym :null) (false))
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def_node_matcher :default_option?, <<-PATTERN
|
35
|
+
(pair (sym :default) !nil)
|
36
|
+
PATTERN
|
37
|
+
|
38
|
+
def on_send(node)
|
39
|
+
check_add_column(node)
|
40
|
+
check_add_reference(node)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def check_add_column(node)
|
46
|
+
pairs = add_not_null_column?(node)
|
47
|
+
check_pairs(pairs)
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_add_reference(node)
|
51
|
+
pairs = add_not_null_reference?(node)
|
52
|
+
check_pairs(pairs)
|
53
|
+
end
|
54
|
+
|
55
|
+
def check_pairs(pairs)
|
56
|
+
return unless pairs
|
57
|
+
return if pairs.any? { |pair| default_option?(pair) }
|
58
|
+
|
59
|
+
null_false = pairs.find { |pair| null_false?(pair) }
|
60
|
+
return unless null_false
|
61
|
+
|
62
|
+
add_offense(null_false)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks for the use of output calls like puts and print
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# puts 'A debug message'
|
11
|
+
# pp 'A debug message'
|
12
|
+
# print 'A debug message'
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# Rails.logger.debug 'A debug message'
|
16
|
+
class Output < Cop
|
17
|
+
MSG = 'Do not write to stdout. ' \
|
18
|
+
"Use Rails's logger if you want to log."
|
19
|
+
|
20
|
+
def_node_matcher :output?, <<-PATTERN
|
21
|
+
(send nil? {:ap :p :pp :pretty_print :print :puts} ...)
|
22
|
+
PATTERN
|
23
|
+
|
24
|
+
def_node_matcher :io_output?, <<-PATTERN
|
25
|
+
(send
|
26
|
+
{
|
27
|
+
(gvar #match_gvar?)
|
28
|
+
{(const nil? :STDOUT) (const nil? :STDERR)}
|
29
|
+
}
|
30
|
+
{:binwrite :syswrite :write :write_nonblock}
|
31
|
+
...)
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def on_send(node)
|
35
|
+
return unless (output?(node) || io_output?(node)) &&
|
36
|
+
node.arguments?
|
37
|
+
|
38
|
+
add_offense(node, location: :selector)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def match_gvar?(sym)
|
44
|
+
%i[$stdout $stderr].include?(sym)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks for the use of output safety calls like `html_safe`,
|
7
|
+
# `raw`, and `safe_concat`. These methods do not escape content. They
|
8
|
+
# simply return a SafeBuffer containing the content as is. Instead,
|
9
|
+
# use `safe_join` to join content and escape it and concat to
|
10
|
+
# concatenate content and escape it, ensuring its safety.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# user_content = "<b>hi</b>"
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# "<p>#{user_content}</p>".html_safe
|
17
|
+
# # => ActiveSupport::SafeBuffer "<p><b>hi</b></p>"
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# content_tag(:p, user_content)
|
21
|
+
# # => ActiveSupport::SafeBuffer "<p><b>hi</b></p>"
|
22
|
+
#
|
23
|
+
# # bad
|
24
|
+
# out = ""
|
25
|
+
# out << "<li>#{user_content}</li>"
|
26
|
+
# out << "<li>#{user_content}</li>"
|
27
|
+
# out.html_safe
|
28
|
+
# # => ActiveSupport::SafeBuffer "<li><b>hi</b></li><li><b>hi</b></li>"
|
29
|
+
#
|
30
|
+
# # good
|
31
|
+
# out = []
|
32
|
+
# out << content_tag(:li, user_content)
|
33
|
+
# out << content_tag(:li, user_content)
|
34
|
+
# safe_join(out)
|
35
|
+
# # => ActiveSupport::SafeBuffer
|
36
|
+
# # "<li><b>hi</b></li><li><b>hi</b></li>"
|
37
|
+
#
|
38
|
+
# # bad
|
39
|
+
# out = "<h1>trusted content</h1>".html_safe
|
40
|
+
# out.safe_concat(user_content)
|
41
|
+
# # => ActiveSupport::SafeBuffer "<h1>trusted_content</h1><b>hi</b>"
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# out = "<h1>trusted content</h1>".html_safe
|
45
|
+
# out.concat(user_content)
|
46
|
+
# # => ActiveSupport::SafeBuffer
|
47
|
+
# # "<h1>trusted_content</h1><b>hi</b>"
|
48
|
+
#
|
49
|
+
# # safe, though maybe not good style
|
50
|
+
# out = "trusted content"
|
51
|
+
# result = out.concat(user_content)
|
52
|
+
# # => String "trusted content<b>hi</b>"
|
53
|
+
# # because when rendered in ERB the String will be escaped:
|
54
|
+
# # <%= result %>
|
55
|
+
# # => trusted content<b>hi</b>
|
56
|
+
#
|
57
|
+
# # bad
|
58
|
+
# (user_content + " " + content_tag(:span, user_content)).html_safe
|
59
|
+
# # => ActiveSupport::SafeBuffer "<b>hi</b> <span><b>hi</b></span>"
|
60
|
+
#
|
61
|
+
# # good
|
62
|
+
# safe_join([user_content, " ", content_tag(:span, user_content)])
|
63
|
+
# # => ActiveSupport::SafeBuffer
|
64
|
+
# # "<b>hi</b> <span><b>hi</b></span>"
|
65
|
+
class OutputSafety < Cop
|
66
|
+
MSG = 'Tagging a string as html safe may be a security risk.'
|
67
|
+
|
68
|
+
def on_send(node)
|
69
|
+
return if non_interpolated_string?(node)
|
70
|
+
|
71
|
+
return unless looks_like_rails_html_safe?(node) ||
|
72
|
+
looks_like_rails_raw?(node) ||
|
73
|
+
looks_like_rails_safe_concat?(node)
|
74
|
+
|
75
|
+
add_offense(node, location: :selector)
|
76
|
+
end
|
77
|
+
alias on_csend on_send
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def non_interpolated_string?(node)
|
82
|
+
node.receiver&.str_type? && !node.receiver.dstr_type?
|
83
|
+
end
|
84
|
+
|
85
|
+
def looks_like_rails_html_safe?(node)
|
86
|
+
node.receiver && node.method?(:html_safe) && !node.arguments?
|
87
|
+
end
|
88
|
+
|
89
|
+
def looks_like_rails_raw?(node)
|
90
|
+
node.command?(:raw) && node.arguments.one?
|
91
|
+
end
|
92
|
+
|
93
|
+
def looks_like_rails_safe_concat?(node)
|
94
|
+
node.method?(:safe_concat) && node.arguments.one?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|