rubocop-rails 2.5.1 → 2.8.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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +192 -11
- data/lib/rubocop/cop/mixin/active_record_helper.rb +22 -0
- data/lib/rubocop/cop/mixin/index_method.rb +25 -1
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +143 -0
- data/lib/rubocop/cop/rails/after_commit_override.rb +84 -0
- data/lib/rubocop/cop/rails/content_tag.rb +69 -0
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +1 -3
- data/lib/rubocop/cop/rails/default_scope.rb +54 -0
- data/lib/rubocop/cop/rails/delegate.rb +2 -4
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +40 -15
- data/lib/rubocop/cop/rails/exit.rb +2 -2
- data/lib/rubocop/cop/rails/file_path.rb +2 -1
- data/lib/rubocop/cop/rails/find_by_id.rb +103 -0
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +1 -5
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +2 -0
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +1 -1
- data/lib/rubocop/cop/rails/http_status.rb +2 -0
- data/lib/rubocop/cop/rails/index_by.rb +8 -0
- data/lib/rubocop/cop/rails/index_with.rb +8 -0
- data/lib/rubocop/cop/rails/inquiry.rb +38 -0
- data/lib/rubocop/cop/rails/inverse_of.rb +0 -4
- data/lib/rubocop/cop/rails/link_to_blank.rb +3 -3
- data/lib/rubocop/cop/rails/mailer_name.rb +80 -0
- data/lib/rubocop/cop/rails/match_route.rb +119 -0
- data/lib/rubocop/cop/rails/negate_include.rb +39 -0
- data/lib/rubocop/cop/rails/order_by_id.rb +53 -0
- data/lib/rubocop/cop/rails/pick.rb +55 -0
- data/lib/rubocop/cop/rails/pluck.rb +59 -0
- data/lib/rubocop/cop/rails/pluck_id.rb +58 -0
- data/lib/rubocop/cop/rails/pluck_in_where.rb +70 -0
- data/lib/rubocop/cop/rails/presence.rb +2 -6
- data/lib/rubocop/cop/rails/rake_environment.rb +17 -0
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +80 -0
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +0 -3
- data/lib/rubocop/cop/rails/reflection_class_name.rb +1 -1
- data/lib/rubocop/cop/rails/relative_date_constant.rb +5 -2
- data/lib/rubocop/cop/rails/render_inline.rb +40 -0
- data/lib/rubocop/cop/rails/render_plain_text.rb +76 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +79 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +1 -1
- data/lib/rubocop/cop/rails/save_bang.rb +8 -9
- data/lib/rubocop/cop/rails/short_i18n.rb +76 -0
- data/lib/rubocop/cop/rails/skips_model_validations.rb +46 -8
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +83 -0
- data/lib/rubocop/cop/rails/time_zone.rb +1 -3
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +14 -12
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +15 -11
- data/lib/rubocop/cop/rails/unknown_env.rb +18 -6
- data/lib/rubocop/cop/rails/where_exists.rb +131 -0
- data/lib/rubocop/cop/rails/where_not.rb +106 -0
- data/lib/rubocop/cop/rails_cops.rb +21 -0
- data/lib/rubocop/rails/schema_loader.rb +10 -10
- data/lib/rubocop/rails/schema_loader/schema.rb +4 -4
- data/lib/rubocop/rails/version.rb +1 -1
- metadata +31 -10
@@ -9,11 +9,11 @@ module RuboCop
|
|
9
9
|
#
|
10
10
|
# There are two obvious cases where `exit` is particularly harmful:
|
11
11
|
#
|
12
|
-
#
|
12
|
+
# * Usage in library code for your application. Even though Rails will
|
13
13
|
# rescue from a `SystemExit` and continue on, unit testing that library
|
14
14
|
# code will result in specs exiting (potentially silently if `exit(0)`
|
15
15
|
# is used.)
|
16
|
-
#
|
16
|
+
# * Usage in application code outside of the web process could result in
|
17
17
|
# the program exiting, which could result in the code failing to run and
|
18
18
|
# do its job.
|
19
19
|
#
|
@@ -48,6 +48,7 @@ module RuboCop
|
|
48
48
|
|
49
49
|
def on_dstr(node)
|
50
50
|
return unless rails_root_nodes?(node)
|
51
|
+
return unless node.children.last.str_type?
|
51
52
|
return unless node.children.last.source.start_with?('.') ||
|
52
53
|
node.children.last.source.include?(File::SEPARATOR)
|
53
54
|
|
@@ -89,7 +90,7 @@ module RuboCop
|
|
89
90
|
end
|
90
91
|
|
91
92
|
def string_with_slash?(node)
|
92
|
-
node.str_type? && node.source
|
93
|
+
node.str_type? && node.source.include?('/')
|
93
94
|
end
|
94
95
|
|
95
96
|
def register_offense(node)
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop enforces that `ActiveRecord#find` is used instead of
|
7
|
+
# `where.take!`, `find_by!`, and `find_by_id!` to retrieve a single record
|
8
|
+
# by primary key when you expect it to be found.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# User.where(id: id).take!
|
13
|
+
# User.find_by_id!(id)
|
14
|
+
# User.find_by!(id: id)
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# User.find(id)
|
18
|
+
#
|
19
|
+
class FindById < Cop
|
20
|
+
include RangeHelp
|
21
|
+
|
22
|
+
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
23
|
+
|
24
|
+
def_node_matcher :where_take?, <<~PATTERN
|
25
|
+
(send
|
26
|
+
$(send _ :where
|
27
|
+
(hash
|
28
|
+
(pair (sym :id) $_))) :take!)
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def_node_matcher :find_by?, <<~PATTERN
|
32
|
+
{
|
33
|
+
(send _ :find_by_id! $_)
|
34
|
+
(send _ :find_by! (hash (pair (sym :id) $_)))
|
35
|
+
}
|
36
|
+
PATTERN
|
37
|
+
|
38
|
+
def on_send(node)
|
39
|
+
where_take?(node) do |where, id_value|
|
40
|
+
range = where_take_offense_range(node, where)
|
41
|
+
|
42
|
+
good_method = build_good_method(id_value)
|
43
|
+
bad_method = build_where_take_bad_method(id_value)
|
44
|
+
message = format(MSG, good_method: good_method, bad_method: bad_method)
|
45
|
+
|
46
|
+
add_offense(node, location: range, message: message)
|
47
|
+
end
|
48
|
+
|
49
|
+
find_by?(node) do |id_value|
|
50
|
+
range = find_by_offense_range(node)
|
51
|
+
|
52
|
+
good_method = build_good_method(id_value)
|
53
|
+
bad_method = build_find_by_bad_method(node, id_value)
|
54
|
+
message = format(MSG, good_method: good_method, bad_method: bad_method)
|
55
|
+
|
56
|
+
add_offense(node, location: range, message: message)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def autocorrect(node)
|
61
|
+
if (matches = where_take?(node))
|
62
|
+
where, id_value = *matches
|
63
|
+
range = where_take_offense_range(node, where)
|
64
|
+
elsif (id_value = find_by?(node))
|
65
|
+
range = find_by_offense_range(node)
|
66
|
+
end
|
67
|
+
|
68
|
+
lambda do |corrector|
|
69
|
+
replacement = build_good_method(id_value)
|
70
|
+
corrector.replace(range, replacement)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def where_take_offense_range(node, where)
|
77
|
+
range_between(where.loc.selector.begin_pos, node.loc.expression.end_pos)
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_by_offense_range(node)
|
81
|
+
range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_good_method(id_value)
|
85
|
+
"find(#{id_value.source})"
|
86
|
+
end
|
87
|
+
|
88
|
+
def build_where_take_bad_method(id_value)
|
89
|
+
"where(id: #{id_value.source}).take!"
|
90
|
+
end
|
91
|
+
|
92
|
+
def build_find_by_bad_method(node, id_value)
|
93
|
+
case node.method_name
|
94
|
+
when :find_by_id!
|
95
|
+
"find_by_id!(#{id_value.source})"
|
96
|
+
when :find_by!
|
97
|
+
"find_by!(id: #{id_value.source})"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -52,11 +52,7 @@ module RuboCop
|
|
52
52
|
|
53
53
|
def on_send(node)
|
54
54
|
return if active_resource?(node.parent)
|
55
|
-
|
56
|
-
unless association_without_options?(node)
|
57
|
-
return if valid_options?(association_with_options?(node))
|
58
|
-
end
|
59
|
-
|
55
|
+
return if !association_without_options?(node) && valid_options?(association_with_options?(node))
|
60
56
|
return if valid_options_in_with_options_block?(node)
|
61
57
|
|
62
58
|
add_offense(node, location: :selector)
|
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
# change them to use keyword args. This cop only applies to Rails >= 5.
|
9
9
|
# If you are running Rails < 5 you should disable the
|
10
10
|
# Rails/HttpPositionalArguments cop or set your TargetRailsVersion in your
|
11
|
-
# .rubocop.yml file to 4.
|
11
|
+
# .rubocop.yml file to 4.2.
|
12
12
|
#
|
13
13
|
# @example
|
14
14
|
# # bad
|
@@ -83,6 +83,7 @@ module RuboCop
|
|
83
83
|
'to define HTTP status code.'
|
84
84
|
|
85
85
|
attr_reader :node
|
86
|
+
|
86
87
|
def initialize(node)
|
87
88
|
@node = node
|
88
89
|
end
|
@@ -124,6 +125,7 @@ module RuboCop
|
|
124
125
|
PERMITTED_STATUS = %i[error success missing redirect].freeze
|
125
126
|
|
126
127
|
attr_reader :node
|
128
|
+
|
127
129
|
def initialize(node)
|
128
130
|
@node = node
|
129
131
|
end
|
@@ -11,6 +11,7 @@ module RuboCop
|
|
11
11
|
# @example
|
12
12
|
# # bad
|
13
13
|
# [1, 2, 3].each_with_object({}) { |el, h| h[foo(el)] = el }
|
14
|
+
# [1, 2, 3].to_h { |el| [foo(el), el] }
|
14
15
|
# [1, 2, 3].map { |el| [foo(el), el] }.to_h
|
15
16
|
# Hash[[1, 2, 3].collect { |el| [foo(el), el] }]
|
16
17
|
#
|
@@ -26,6 +27,13 @@ module RuboCop
|
|
26
27
|
({send csend} (lvar _memo) :[]= $_ (lvar _el)))
|
27
28
|
PATTERN
|
28
29
|
|
30
|
+
def_node_matcher :on_bad_to_h, <<~PATTERN
|
31
|
+
(block
|
32
|
+
({send csend} _ :to_h)
|
33
|
+
(args (arg $_el))
|
34
|
+
(array $_ (lvar _el)))
|
35
|
+
PATTERN
|
36
|
+
|
29
37
|
def_node_matcher :on_bad_map_to_h, <<~PATTERN
|
30
38
|
({send csend}
|
31
39
|
(block
|
@@ -11,6 +11,7 @@ module RuboCop
|
|
11
11
|
# @example
|
12
12
|
# # bad
|
13
13
|
# [1, 2, 3].each_with_object({}) { |el, h| h[el] = foo(el) }
|
14
|
+
# [1, 2, 3].to_h { |el| [el, foo(el)] }
|
14
15
|
# [1, 2, 3].map { |el| [el, foo(el)] }.to_h
|
15
16
|
# Hash[[1, 2, 3].collect { |el| [el, foo(el)] }]
|
16
17
|
#
|
@@ -29,6 +30,13 @@ module RuboCop
|
|
29
30
|
({send csend} (lvar _memo) :[]= (lvar _el) $_))
|
30
31
|
PATTERN
|
31
32
|
|
33
|
+
def_node_matcher :on_bad_to_h, <<~PATTERN
|
34
|
+
(block
|
35
|
+
({send csend} _ :to_h)
|
36
|
+
(args (arg $_el))
|
37
|
+
(array (lvar _el) $_))
|
38
|
+
PATTERN
|
39
|
+
|
32
40
|
def_node_matcher :on_bad_map_to_h, <<~PATTERN
|
33
41
|
({send csend}
|
34
42
|
(block
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks that Active Support's `inquiry` method is not used.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad - String#inquiry
|
10
|
+
# ruby = 'two'.inquiry
|
11
|
+
# ruby.two?
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# ruby = 'two'
|
15
|
+
# ruby == 'two'
|
16
|
+
#
|
17
|
+
# # bad - Array#inquiry
|
18
|
+
# pets = %w(cat dog).inquiry
|
19
|
+
# pets.gopher?
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# pets = %w(cat dog)
|
23
|
+
# pets.include? 'cat'
|
24
|
+
#
|
25
|
+
class Inquiry < Cop
|
26
|
+
MSG = "Prefer Ruby's comparison operators over Active Support's `inquiry`."
|
27
|
+
|
28
|
+
def on_send(node)
|
29
|
+
return unless node.method?(:inquiry) && node.arguments.empty?
|
30
|
+
return unless (receiver = node.receiver)
|
31
|
+
return if !receiver.str_type? && !receiver.array_type?
|
32
|
+
|
33
|
+
add_offense(node, location: :selector)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -129,10 +129,6 @@ module RuboCop
|
|
129
129
|
# @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
|
130
130
|
# @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
|
131
131
|
class InverseOf < Cop
|
132
|
-
extend TargetRailsVersion
|
133
|
-
|
134
|
-
minimum_target_rails_version 4.1
|
135
|
-
|
136
132
|
SPECIFY_MSG = 'Specify an `:inverse_of` option.'
|
137
133
|
NIL_MSG = 'You specified `inverse_of: nil`, you probably meant to ' \
|
138
134
|
'use `inverse_of: false`.'
|
@@ -35,6 +35,7 @@ module RuboCop
|
|
35
35
|
(pair {(sym :rel) (str "rel")} (str _))
|
36
36
|
PATTERN
|
37
37
|
|
38
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
38
39
|
def on_send(node)
|
39
40
|
return unless node.method?(:link_to)
|
40
41
|
|
@@ -42,11 +43,10 @@ module RuboCop
|
|
42
43
|
|
43
44
|
option_nodes.map(&:children).each do |options|
|
44
45
|
blank = options.find { |o| blank_target?(o) }
|
45
|
-
if blank && options.none? { |o| includes_noopener?(o) }
|
46
|
-
add_offense(blank)
|
47
|
-
end
|
46
|
+
add_offense(blank) if blank && options.none? { |o| includes_noopener?(o) }
|
48
47
|
end
|
49
48
|
end
|
49
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
50
50
|
|
51
51
|
def autocorrect(node)
|
52
52
|
lambda do |corrector|
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop enforces that mailer names end with `Mailer` suffix.
|
7
|
+
#
|
8
|
+
# Without the `Mailer` suffix it isn't immediately apparent what's a mailer
|
9
|
+
# and which views are related to the mailer.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# class User < ActionMailer::Base
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# class User < ApplicationMailer
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# class UserMailer < ActionMailer::Base
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# class UserMailer < ApplicationMailer
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
class MailerName < Cop
|
27
|
+
MSG = 'Mailer should end with `Mailer` suffix.'
|
28
|
+
|
29
|
+
def_node_matcher :mailer_base_class?, <<~PATTERN
|
30
|
+
{
|
31
|
+
(const (const nil? :ActionMailer) :Base)
|
32
|
+
(const nil? :ApplicationMailer)
|
33
|
+
}
|
34
|
+
PATTERN
|
35
|
+
|
36
|
+
def_node_matcher :class_definition?, <<~PATTERN
|
37
|
+
(class $(const _ !#mailer_suffix?) #mailer_base_class? ...)
|
38
|
+
PATTERN
|
39
|
+
|
40
|
+
def_node_matcher :class_new_definition?, <<~PATTERN
|
41
|
+
(send (const nil? :Class) :new #mailer_base_class?)
|
42
|
+
PATTERN
|
43
|
+
|
44
|
+
def on_class(node)
|
45
|
+
class_definition?(node) do |name_node|
|
46
|
+
add_offense(name_node)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def on_send(node)
|
51
|
+
return unless class_new_definition?(node)
|
52
|
+
|
53
|
+
casgn_parent = node.each_ancestor(:casgn).first
|
54
|
+
return unless casgn_parent
|
55
|
+
|
56
|
+
name = casgn_parent.children[1]
|
57
|
+
add_offense(casgn_parent, location: :name) unless mailer_suffix?(name)
|
58
|
+
end
|
59
|
+
|
60
|
+
def autocorrect(node)
|
61
|
+
lambda do |corrector|
|
62
|
+
if node.casgn_type?
|
63
|
+
name = node.children[1]
|
64
|
+
corrector.replace(node.loc.name, "#{name}Mailer")
|
65
|
+
else
|
66
|
+
name = node.children.last
|
67
|
+
corrector.replace(node.source_range, "#{name}Mailer")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def mailer_suffix?(mailer_name)
|
75
|
+
mailer_name.to_s.end_with?('Mailer')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop identifies places where defining routes with `match`
|
7
|
+
# can be replaced with a specific HTTP method.
|
8
|
+
#
|
9
|
+
# Don't use `match` to define any routes unless there is a need to map multiple request types
|
10
|
+
# among [:get, :post, :patch, :put, :delete] to a single action using the `:via` option.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# # bad
|
14
|
+
# match ':controller/:action/:id'
|
15
|
+
# match 'photos/:id', to: 'photos#show', via: :get
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# get ':controller/:action/:id'
|
19
|
+
# get 'photos/:id', to: 'photos#show'
|
20
|
+
# match 'photos/:id', to: 'photos#show', via: [:get, :post]
|
21
|
+
# match 'photos/:id', to: 'photos#show', via: :all
|
22
|
+
#
|
23
|
+
class MatchRoute < Cop
|
24
|
+
MSG = 'Use `%<http_method>s` instead of `match` to define a route.'
|
25
|
+
HTTP_METHODS = %i[get post put patch delete].freeze
|
26
|
+
|
27
|
+
def_node_matcher :match_method_call?, <<~PATTERN
|
28
|
+
(send nil? :match $_ $(hash ...) ?)
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def on_send(node)
|
32
|
+
match_method_call?(node) do |path_node, options_node|
|
33
|
+
return unless within_routes?(node)
|
34
|
+
|
35
|
+
options_node = path_node.hash_type? ? path_node : options_node.first
|
36
|
+
|
37
|
+
if options_node.nil?
|
38
|
+
message = format(MSG, http_method: 'get')
|
39
|
+
add_offense(node, message: message)
|
40
|
+
else
|
41
|
+
via = extract_via(options_node)
|
42
|
+
if via.size == 1 && http_method?(via.first)
|
43
|
+
message = format(MSG, http_method: via.first)
|
44
|
+
add_offense(node, message: message)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def autocorrect(node)
|
51
|
+
match_method_call?(node) do |path_node, options_node|
|
52
|
+
options_node = options_node.first
|
53
|
+
|
54
|
+
lambda do |corrector|
|
55
|
+
corrector.replace(node, replacement(path_node, options_node))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def_node_matcher :routes_draw?, <<~PATTERN
|
63
|
+
(send (send _ :routes) :draw)
|
64
|
+
PATTERN
|
65
|
+
|
66
|
+
def within_routes?(node)
|
67
|
+
node.each_ancestor(:block).any? { |a| routes_draw?(a.send_node) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def extract_via(node)
|
71
|
+
via_pair = via_pair(node)
|
72
|
+
return %i[get] unless via_pair
|
73
|
+
|
74
|
+
_, via = *via_pair
|
75
|
+
|
76
|
+
if via.basic_literal?
|
77
|
+
[via.value]
|
78
|
+
elsif via.array_type?
|
79
|
+
via.values.map(&:value)
|
80
|
+
else
|
81
|
+
[]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def via_pair(node)
|
86
|
+
node.pairs.find { |p| p.key.value == :via }
|
87
|
+
end
|
88
|
+
|
89
|
+
def http_method?(method)
|
90
|
+
HTTP_METHODS.include?(method.to_sym)
|
91
|
+
end
|
92
|
+
|
93
|
+
def replacement(path_node, options_node)
|
94
|
+
if path_node.hash_type?
|
95
|
+
http_method, options = *http_method_and_options(path_node)
|
96
|
+
"#{http_method} #{options.map(&:source).join(', ')}"
|
97
|
+
elsif options_node.nil?
|
98
|
+
"get #{path_node.source}"
|
99
|
+
else
|
100
|
+
http_method, options = *http_method_and_options(options_node)
|
101
|
+
|
102
|
+
if options.any?
|
103
|
+
"#{http_method} #{path_node.source}, #{options.map(&:source).join(', ')}"
|
104
|
+
else
|
105
|
+
"#{http_method} #{path_node.source}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def http_method_and_options(node)
|
111
|
+
via_pair = via_pair(node)
|
112
|
+
http_method = extract_via(node).first
|
113
|
+
rest_pairs = node.pairs - [via_pair]
|
114
|
+
[http_method, rest_pairs]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|