/
validation.rb
105 lines (92 loc) · 2.95 KB
/
validation.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# frozen_string_literal: true
module RuboCop
module Cop
module Rails
# This cop checks for the use of old-style attribute validation macros.
#
# @example
# # bad
# validates_acceptance_of :foo
# validates_confirmation_of :foo
# validates_exclusion_of :foo
# validates_format_of :foo
# validates_inclusion_of :foo
# validates_length_of :foo
# validates_numericality_of :foo
# validates_presence_of :foo
# validates_size_of :foo
# validates_uniqueness_of :foo
#
# # good
# validates :foo, acceptance: true
# validates :foo, confirmation: true
# validates :foo, exclusion: true
# validates :foo, format: true
# validates :foo, inclusion: true
# validates :foo, length: true
# validates :foo, numericality: true
# validates :foo, presence: true
# validates :foo, size: true
# validates :foo, uniqueness: true
#
class Validation < Cop
MSG = 'Prefer the new style validations `%<prefer>s` over ' \
'`%<current>s`.'.freeze
TYPES = %w[
acceptance
confirmation
exclusion
format
inclusion
length
numericality
presence
size
uniqueness
].freeze
DENYLIST = TYPES.map { |p| "validates_#{p}_of".to_sym }.freeze
ALLOWLIST = TYPES.map { |p| "validates :column, #{p}: value" }.freeze
def on_send(node)
return unless !node.receiver && DENYLIST.include?(node.method_name)
add_offense(node, location: :selector)
end
def autocorrect(node)
last_argument = node.arguments.last
return if !last_argument.literal? && !last_argument.splat_type?
lambda do |corrector|
corrector.replace(node.loc.selector, 'validates')
correct_validate_type(corrector, node)
end
end
private
def message(node)
format(MSG, prefer: preferred_method(node.method_name),
current: node.method_name)
end
def preferred_method(method)
ALLOWLIST[DENYLIST.index(method.to_sym)]
end
def correct_validate_type(corrector, node)
last_argument = node.arguments.last
validate_type = node.method_name.to_s.split('_')[1]
if last_argument.hash_type?
corrector.replace(
last_argument.loc.expression,
"#{validate_type}: #{braced_options(last_argument)}"
)
else
corrector.insert_after(node.loc.expression,
", #{validate_type}: true")
end
end
def braced_options(options)
if options.braces?
options.source
else
"{ #{options.source} }"
end
end
end
end
end
end