Skip to content

Commit 67a799f

Browse files
authored
refactor: use lambda based validators (#11)
Improves the abstraction of limit validations by building lambdas to pass to the validate method
1 parent 7400457 commit 67a799f

File tree

2 files changed

+28
-24
lines changed

2 files changed

+28
-24
lines changed

.rubocop.yml

+7
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,10 @@ AllCops:
99
- gemfiles/**/*
1010
NewCops: enable
1111
TargetRubyVersion: 3.0
12+
13+
Metrics/AbcSize:
14+
CountRepeatedAttributes: false
15+
Max: 20
16+
17+
Metrics/MethodLength:
18+
Max: 12

lib/limitable.rb

+21-24
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module Limitable
1414
class << self
1515
def included(klass)
1616
safe_column_names(klass).each do |column_name|
17-
add_limit_validation klass, column_name
17+
attach_limit_validator_if_needed klass, column_name
1818
end
1919
end
2020

@@ -26,50 +26,47 @@ def safe_column_names(klass)
2626
[]
2727
end
2828

29-
def add_limit_validation(klass, column_name)
29+
def attach_limit_validator_if_needed(klass, column_name)
3030
column = klass.column_for_attribute column_name
3131
limit = column.sql_type_metadata.limit
3232
return if limit.blank?
3333

3434
case column.type
3535
when :integer
36-
add_integer_limit_validation klass, column_name, limit
36+
klass.validate(&build_integer_limit_validator(column_name, limit))
3737
when :string, :text
38-
add_string_limit_validation klass, column_name, limit
38+
klass.validate(&build_string_limit_validator(column_name, limit))
3939
end
4040
end
4141

42-
def add_integer_limit_validation(klass, column_name, limit)
42+
def build_integer_limit_validator(column_name, limit)
4343
min, max = integer_limit_range limit
44-
integer_type_normalizer = method :integer_type_normalizer
45-
klass.validate do
46-
value = integer_type_normalizer.call klass, column_name, self[column_name]
47-
next unless value.is_a?(Integer)
44+
lambda do
45+
value = begin
46+
self.class.type_for_attribute(column_name).serialize self[column_name]
47+
rescue ActiveModel::RangeError => e
48+
e.message.match(/(?<number>\d+) is out of range/)[:number].to_i
49+
end
50+
next unless value.is_a? Integer
4851

4952
errors.add column_name, I18n.t('errors.messages.greater_than_or_equal_to', count: min) if value < min
5053
errors.add column_name, I18n.t('errors.messages.less_than_or_equal_to', count: max) if value > max
5154
end
5255
end
5356

54-
def integer_limit_range(limit)
55-
max = (1 << ((limit * 8) - 1)) - 1
56-
min = -max
57-
[min, max]
58-
end
59-
60-
def integer_type_normalizer(klass, column_name, value)
61-
klass.type_for_attribute(column_name).serialize value
62-
rescue ActiveModel::RangeError => e
63-
e.message.match(/(?<number>\d+) is out of range/)[:number].to_i
64-
end
65-
66-
def add_string_limit_validation(klass, column_name, limit)
67-
klass.validate do
68-
value = klass.type_for_attribute(column_name).serialize self[column_name]
57+
def build_string_limit_validator(column_name, limit)
58+
lambda do
59+
value = self.class.type_for_attribute(column_name).serialize self[column_name]
6960
next unless value.is_a?(String) && value.bytesize > limit
7061

7162
errors.add column_name, I18n.t('errors.messages.too_long.other', count: limit)
7263
end
7364
end
65+
66+
def integer_limit_range(limit)
67+
max = (1 << ((limit * 8) - 1)) - 1
68+
min = -max
69+
[min, max]
70+
end
7471
end
7572
end

0 commit comments

Comments
 (0)