aequitas 0.0.1
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.
- data/.gitignore +4 -0
- data/.rvmrc +1 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.rdoc +125 -0
- data/Rakefile +25 -0
- data/VERSION +1 -0
- data/aequitas.gemspec +20 -0
- data/lib/aequitas.rb +80 -0
- data/lib/aequitas/class_methods.rb +26 -0
- data/lib/aequitas/context.rb +53 -0
- data/lib/aequitas/contextual_rule_set.rb +221 -0
- data/lib/aequitas/exceptions.rb +10 -0
- data/lib/aequitas/macros.rb +466 -0
- data/lib/aequitas/message_transformer.rb +127 -0
- data/lib/aequitas/rule.rb +153 -0
- data/lib/aequitas/rule/absence.rb +14 -0
- data/lib/aequitas/rule/absence/blank.rb +21 -0
- data/lib/aequitas/rule/absence/nil.rb +21 -0
- data/lib/aequitas/rule/acceptance.rb +36 -0
- data/lib/aequitas/rule/block.rb +33 -0
- data/lib/aequitas/rule/confirmation.rb +41 -0
- data/lib/aequitas/rule/format.rb +81 -0
- data/lib/aequitas/rule/format/proc.rb +28 -0
- data/lib/aequitas/rule/format/regexp.rb +44 -0
- data/lib/aequitas/rule/formats/email.rb +52 -0
- data/lib/aequitas/rule/formats/url.rb +14 -0
- data/lib/aequitas/rule/guard.rb +51 -0
- data/lib/aequitas/rule/length.rb +87 -0
- data/lib/aequitas/rule/length/equal.rb +46 -0
- data/lib/aequitas/rule/length/maximum.rb +46 -0
- data/lib/aequitas/rule/length/minimum.rb +46 -0
- data/lib/aequitas/rule/length/range.rb +46 -0
- data/lib/aequitas/rule/method.rb +31 -0
- data/lib/aequitas/rule/numericalness.rb +85 -0
- data/lib/aequitas/rule/numericalness/equal.rb +30 -0
- data/lib/aequitas/rule/numericalness/greater_than.rb +30 -0
- data/lib/aequitas/rule/numericalness/greater_than_or_equal.rb +30 -0
- data/lib/aequitas/rule/numericalness/integer.rb +37 -0
- data/lib/aequitas/rule/numericalness/less_than.rb +30 -0
- data/lib/aequitas/rule/numericalness/less_than_or_equal.rb +30 -0
- data/lib/aequitas/rule/numericalness/non_integer.rb +64 -0
- data/lib/aequitas/rule/numericalness/not_equal.rb +30 -0
- data/lib/aequitas/rule/presence.rb +14 -0
- data/lib/aequitas/rule/presence/not_blank.rb +21 -0
- data/lib/aequitas/rule/presence/not_nil.rb +21 -0
- data/lib/aequitas/rule/primitive_type.rb +28 -0
- data/lib/aequitas/rule/skip_condition.rb +104 -0
- data/lib/aequitas/rule/within.rb +28 -0
- data/lib/aequitas/rule/within/range.rb +53 -0
- data/lib/aequitas/rule/within/range/bounded.rb +25 -0
- data/lib/aequitas/rule/within/range/unbounded_begin.rb +25 -0
- data/lib/aequitas/rule/within/range/unbounded_end.rb +25 -0
- data/lib/aequitas/rule/within/set.rb +39 -0
- data/lib/aequitas/rule_set.rb +80 -0
- data/lib/aequitas/support/blank.rb +22 -0
- data/lib/aequitas/support/equalizable.rb +113 -0
- data/lib/aequitas/support/ordered_hash.rb +438 -0
- data/lib/aequitas/version.rb +5 -0
- data/lib/aequitas/violation.rb +116 -0
- data/lib/aequitas/violation_set.rb +123 -0
- data/lib/aequitas/virtus.rb +29 -0
- data/lib/aequitas/virtus/inline_attribute_rule_extractor.rb +41 -0
- data/lib/aequitas/virtus/inline_attribute_rule_extractor/boolean.rb +17 -0
- data/lib/aequitas/virtus/inline_attribute_rule_extractor/object.rb +25 -0
- data/lib/aequitas/virtus/inline_attribute_rule_extractor/string.rb +27 -0
- data/spec/integration/aequitas/macros/validates_absence_of_spec.rb +19 -0
- data/spec/integration/aequitas/macros/validates_acceptance_of_spec.rb +19 -0
- data/spec/integration/aequitas/macros/validates_confirmation_of_spec.rb +25 -0
- data/spec/integration/aequitas/macros/validates_format_of_spec.rb +87 -0
- data/spec/integration/aequitas/macros/validates_length_of.rb +77 -0
- data/spec/integration/aequitas/macros/validates_numericalness_of_spec.rb +221 -0
- data/spec/integration/aequitas/macros/validates_presence_of_spec.rb +19 -0
- data/spec/integration/aequitas/macros/validates_with_block.rb +23 -0
- data/spec/integration/aequitas/macros/validates_with_method.rb +19 -0
- data/spec/integration/aequitas/macros/validates_within.rb +87 -0
- data/spec/integration/shared/macros/integration_spec.rb +67 -0
- data/spec/integration/virtus/boolean/presence_spec.rb +49 -0
- data/spec/integration/virtus/string/format/email_address_spec.rb +55 -0
- data/spec/integration/virtus/string/format/regexp_spec.rb +55 -0
- data/spec/integration/virtus/string/format/url_spec.rb +55 -0
- data/spec/integration/virtus/string/length/equal_spec.rb +49 -0
- data/spec/integration/virtus/string/length/range_spec.rb +49 -0
- data/spec/integration/virtus/string/presence_spec.rb +49 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/suite.rb +5 -0
- data/spec/unit/aequitas/rule/absence/blank_spec.rb +45 -0
- data/spec/unit/aequitas/rule/acceptance_spec.rb +71 -0
- data/spec/unit/aequitas/rule/confirmation_spec.rb +80 -0
- data/spec/unit/aequitas/rule/guard_spec.rb +120 -0
- data/spec/unit/aequitas/rule/skip_condition_spec.rb +170 -0
- data/spec/unit/aequitas/rule_spec.rb +40 -0
- data/spec/unit/aequitas/support/blank_spec.rb +83 -0
- data/spec/unit/aequitas/support/equalizable/equalizer_spec.rb +21 -0
- data/spec/unit/aequitas/support/equalizable_spec.rb +67 -0
- data/spec/unit/aequitas/violation_set_spec.rb +154 -0
- data/spec_legacy/fixtures/barcode.rb +40 -0
- data/spec_legacy/fixtures/basketball_court.rb +58 -0
- data/spec_legacy/fixtures/basketball_player.rb +34 -0
- data/spec_legacy/fixtures/beta_tester_account.rb +33 -0
- data/spec_legacy/fixtures/bill_of_landing.rb +47 -0
- data/spec_legacy/fixtures/boat_dock.rb +26 -0
- data/spec_legacy/fixtures/city.rb +24 -0
- data/spec_legacy/fixtures/company.rb +93 -0
- data/spec_legacy/fixtures/corporate_world.rb +39 -0
- data/spec_legacy/fixtures/country.rb +24 -0
- data/spec_legacy/fixtures/ethernet_frame.rb +56 -0
- data/spec_legacy/fixtures/event.rb +44 -0
- data/spec_legacy/fixtures/g3_concert.rb +57 -0
- data/spec_legacy/fixtures/jabberwock.rb +27 -0
- data/spec_legacy/fixtures/kayak.rb +28 -0
- data/spec_legacy/fixtures/lernean_hydra.rb +39 -0
- data/spec_legacy/fixtures/llama_spaceship.rb +15 -0
- data/spec_legacy/fixtures/mathematical_function.rb +34 -0
- data/spec_legacy/fixtures/memory_object.rb +30 -0
- data/spec_legacy/fixtures/mittelschnauzer.rb +39 -0
- data/spec_legacy/fixtures/motor_launch.rb +21 -0
- data/spec_legacy/fixtures/multibyte.rb +16 -0
- data/spec_legacy/fixtures/page.rb +32 -0
- data/spec_legacy/fixtures/phone_number.rb +28 -0
- data/spec_legacy/fixtures/pirogue.rb +28 -0
- data/spec_legacy/fixtures/programming_language.rb +83 -0
- data/spec_legacy/fixtures/reservation.rb +38 -0
- data/spec_legacy/fixtures/scm_operation.rb +56 -0
- data/spec_legacy/fixtures/sms_message.rb +22 -0
- data/spec_legacy/fixtures/udp_packet.rb +49 -0
- data/spec_legacy/integration/absent_field_validator/absent_field_validator_spec.rb +90 -0
- data/spec_legacy/integration/absent_field_validator/spec_helper.rb +7 -0
- data/spec_legacy/integration/acceptance_validator/acceptance_validator_spec.rb +196 -0
- data/spec_legacy/integration/acceptance_validator/spec_helper.rb +7 -0
- data/spec_legacy/integration/automatic_validation/custom_messages_for_inferred_validation_spec.rb +57 -0
- data/spec_legacy/integration/automatic_validation/disabling_inferred_validation_spec.rb +49 -0
- data/spec_legacy/integration/automatic_validation/inferred_boolean_properties_validation_spec.rb +100 -0
- data/spec_legacy/integration/automatic_validation/inferred_float_property_validation_spec.rb +45 -0
- data/spec_legacy/integration/automatic_validation/inferred_format_validation_spec.rb +35 -0
- data/spec_legacy/integration/automatic_validation/inferred_integer_properties_validation_spec.rb +70 -0
- data/spec_legacy/integration/automatic_validation/inferred_length_validation_spec.rb +142 -0
- data/spec_legacy/integration/automatic_validation/inferred_presence_validation_spec.rb +45 -0
- data/spec_legacy/integration/automatic_validation/inferred_primitive_validation_spec.rb +22 -0
- data/spec_legacy/integration/automatic_validation/inferred_uniqueness_validation_spec.rb +48 -0
- data/spec_legacy/integration/automatic_validation/inferred_within_validation_spec.rb +35 -0
- data/spec_legacy/integration/automatic_validation/spec_helper.rb +57 -0
- data/spec_legacy/integration/block_validator/block_validator_spec.rb +32 -0
- data/spec_legacy/integration/block_validator/spec_helper.rb +5 -0
- data/spec_legacy/integration/conditional_validation/if_condition_spec.rb +63 -0
- data/spec_legacy/integration/conditional_validation/spec_helper.rb +5 -0
- data/spec_legacy/integration/confirmation_validator/confirmation_validator_spec.rb +76 -0
- data/spec_legacy/integration/confirmation_validator/spec_helper.rb +5 -0
- data/spec_legacy/integration/datamapper_models/association_validation_spec.rb +29 -0
- data/spec_legacy/integration/datamapper_models/inheritance_spec.rb +82 -0
- data/spec_legacy/integration/dirty_attributes/dirty_attributes_spec.rb +13 -0
- data/spec_legacy/integration/duplicated_validations/duplicated_validations_spec.rb +24 -0
- data/spec_legacy/integration/duplicated_validations/spec_helper.rb +5 -0
- data/spec_legacy/integration/format_validator/email_format_validator_spec.rb +139 -0
- data/spec_legacy/integration/format_validator/format_validator_spec.rb +64 -0
- data/spec_legacy/integration/format_validator/regexp_validator_spec.rb +33 -0
- data/spec_legacy/integration/format_validator/spec_helper.rb +5 -0
- data/spec_legacy/integration/format_validator/url_format_validator_spec.rb +93 -0
- data/spec_legacy/integration/length_validator/default_value_spec.rb +14 -0
- data/spec_legacy/integration/length_validator/equality_spec.rb +87 -0
- data/spec_legacy/integration/length_validator/error_message_spec.rb +22 -0
- data/spec_legacy/integration/length_validator/maximum_spec.rb +49 -0
- data/spec_legacy/integration/length_validator/minimum_spec.rb +54 -0
- data/spec_legacy/integration/length_validator/range_spec.rb +87 -0
- data/spec_legacy/integration/length_validator/spec_helper.rb +7 -0
- data/spec_legacy/integration/method_validator/method_validator_spec.rb +242 -0
- data/spec_legacy/integration/method_validator/spec_helper.rb +5 -0
- data/spec_legacy/integration/numeric_validator/equality_with_float_type_spec.rb +65 -0
- data/spec_legacy/integration/numeric_validator/equality_with_integer_type_spec.rb +41 -0
- data/spec_legacy/integration/numeric_validator/float_type_spec.rb +90 -0
- data/spec_legacy/integration/numeric_validator/gt_with_float_type_spec.rb +37 -0
- data/spec_legacy/integration/numeric_validator/gte_with_float_type_spec.rb +37 -0
- data/spec_legacy/integration/numeric_validator/integer_only_true_spec.rb +91 -0
- data/spec_legacy/integration/numeric_validator/integer_type_spec.rb +86 -0
- data/spec_legacy/integration/numeric_validator/lt_with_float_type_spec.rb +37 -0
- data/spec_legacy/integration/numeric_validator/lte_with_float_type_spec.rb +37 -0
- data/spec_legacy/integration/numeric_validator/spec_helper.rb +5 -0
- data/spec_legacy/integration/primitive_validator/primitive_validator_spec.rb +92 -0
- data/spec_legacy/integration/primitive_validator/spec_helper.rb +5 -0
- data/spec_legacy/integration/pure_ruby_objects/plain_old_ruby_object_validation_spec.rb +118 -0
- data/spec_legacy/integration/required_field_validator/association_spec.rb +69 -0
- data/spec_legacy/integration/required_field_validator/boolean_type_value_spec.rb +164 -0
- data/spec_legacy/integration/required_field_validator/date_type_value_spec.rb +127 -0
- data/spec_legacy/integration/required_field_validator/datetime_type_value_spec.rb +127 -0
- data/spec_legacy/integration/required_field_validator/float_type_value_spec.rb +131 -0
- data/spec_legacy/integration/required_field_validator/integer_type_value_spec.rb +99 -0
- data/spec_legacy/integration/required_field_validator/plain_old_ruby_object_spec.rb +35 -0
- data/spec_legacy/integration/required_field_validator/shared_examples.rb +26 -0
- data/spec_legacy/integration/required_field_validator/spec_helper.rb +7 -0
- data/spec_legacy/integration/required_field_validator/string_type_value_spec.rb +167 -0
- data/spec_legacy/integration/required_field_validator/text_type_value_spec.rb +49 -0
- data/spec_legacy/integration/shared/default_validation_context.rb +13 -0
- data/spec_legacy/integration/shared/valid_and_invalid_model.rb +35 -0
- data/spec_legacy/integration/uniqueness_validator/spec_helper.rb +5 -0
- data/spec_legacy/integration/uniqueness_validator/uniqueness_validator_spec.rb +116 -0
- data/spec_legacy/integration/within_validator/spec_helper.rb +5 -0
- data/spec_legacy/integration/within_validator/within_validator_spec.rb +168 -0
- data/spec_legacy/public/resource_spec.rb +105 -0
- data/spec_legacy/spec.opts +4 -0
- data/spec_legacy/spec_helper.rb +29 -0
- data/spec_legacy/unit/contextual_validators/emptiness_spec.rb +50 -0
- data/spec_legacy/unit/contextual_validators/execution_spec.rb +48 -0
- data/spec_legacy/unit/contextual_validators/spec_helper.rb +37 -0
- data/spec_legacy/unit/generic_validator/equality_operator_spec.rb +26 -0
- data/spec_legacy/unit/generic_validator/optional_spec.rb +54 -0
- data/spec_legacy/unit/validators/within_validator_spec.rb +23 -0
- data/spec_legacy/unit/violation_set/adding_spec.rb +54 -0
- data/spec_legacy/unit/violation_set/emptiness_spec.rb +38 -0
- data/spec_legacy/unit/violation_set/enumerable_spec.rb +32 -0
- data/spec_legacy/unit/violation_set/reading_spec.rb +35 -0
- data/spec_legacy/unit/violation_set/respond_to_spec.rb +15 -0
- data/tasks/spec.rake +38 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +302 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/rule'
|
|
4
|
+
require 'aequitas/exceptions'
|
|
5
|
+
|
|
6
|
+
require 'aequitas/rule/formats/email'
|
|
7
|
+
require 'aequitas/rule/formats/url'
|
|
8
|
+
|
|
9
|
+
module Aequitas
|
|
10
|
+
class Rule
|
|
11
|
+
module Format
|
|
12
|
+
|
|
13
|
+
FORMATS = {
|
|
14
|
+
:email_address => Formats::EmailAddress,
|
|
15
|
+
:url => Formats::Url
|
|
16
|
+
}
|
|
17
|
+
# TODO: evaluate re-implementing custom error messages per format type
|
|
18
|
+
# previously these strings were wrapped in lambdas, which were, at one
|
|
19
|
+
# point, invoked with #try_call with the humanized attribute name and value
|
|
20
|
+
FORMAT_MESSAGES = {
|
|
21
|
+
:email_address => '%s is not a valid email address',
|
|
22
|
+
:url => '%s is not a valid URL',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def self.rules_for(attribute_name, options)
|
|
27
|
+
Array(new(attribute_name, options))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @raise [UnknownValidationFormat]
|
|
31
|
+
# if the :as (or :with) option is a Symbol that is not a key in FORMATS,
|
|
32
|
+
# or if the provided format is not a Regexp, Symbol or Proc
|
|
33
|
+
def self.new(attribute_name, options)
|
|
34
|
+
format = options.delete(:as) || options.delete(:with)
|
|
35
|
+
|
|
36
|
+
case format
|
|
37
|
+
when Symbol
|
|
38
|
+
regexp = FORMATS.fetch(format) do
|
|
39
|
+
raise UnknownValidationFormat, "No such predefined format '#{format}'"
|
|
40
|
+
end
|
|
41
|
+
self::Regexp.new(attribute_name, options.merge(:format => regexp, :format_name => format))
|
|
42
|
+
when ::Regexp
|
|
43
|
+
self::Regexp.new(attribute_name, options.merge(:format => format))
|
|
44
|
+
when ::Proc
|
|
45
|
+
self::Proc.new(attribute_name, options.merge(:format => format))
|
|
46
|
+
else
|
|
47
|
+
raise UnknownValidationFormat, "Expected a Regexp, Symbol, or Proc format. Got: #{format.inspect}"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
attr_reader :format
|
|
53
|
+
|
|
54
|
+
def initialize(attribute_name, options)
|
|
55
|
+
super
|
|
56
|
+
|
|
57
|
+
@format = options.fetch(:format)
|
|
58
|
+
|
|
59
|
+
skip_condition.default_to_allowing_nil!
|
|
60
|
+
skip_condition.default_to_allowing_blank!
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def violation_type(resource)
|
|
64
|
+
:invalid
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# TODO: integrate format into error message key?
|
|
68
|
+
# def error_message_args
|
|
69
|
+
# if format.is_a?(Symbol)
|
|
70
|
+
# [ :"invalid_#{format}", attribute_name ]
|
|
71
|
+
# else
|
|
72
|
+
# [ :invalid, attribute_name ]
|
|
73
|
+
# end
|
|
74
|
+
# end
|
|
75
|
+
|
|
76
|
+
end # class Format
|
|
77
|
+
end # class Rule
|
|
78
|
+
end # module Aequitas
|
|
79
|
+
|
|
80
|
+
require 'aequitas/rule/format/proc'
|
|
81
|
+
require 'aequitas/rule/format/regexp'
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/rule/format'
|
|
4
|
+
|
|
5
|
+
module Aequitas
|
|
6
|
+
class Rule
|
|
7
|
+
module Format
|
|
8
|
+
class Proc < Rule
|
|
9
|
+
|
|
10
|
+
include Format
|
|
11
|
+
|
|
12
|
+
equalize_on *(superclass.equalizer.keys + [:format])
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def valid?(resource)
|
|
16
|
+
value = attribute_value(resource)
|
|
17
|
+
return true if skip?(value)
|
|
18
|
+
|
|
19
|
+
self.format.call(value)
|
|
20
|
+
# rescue ::Encoding::CompatibilityError
|
|
21
|
+
# # This is to work around a bug in jruby - see formats/email.rb
|
|
22
|
+
# false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end # class Proc
|
|
26
|
+
end # module Format
|
|
27
|
+
end # class Rule
|
|
28
|
+
end # module Aequitas
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/rule/format'
|
|
4
|
+
|
|
5
|
+
module Aequitas
|
|
6
|
+
class Rule
|
|
7
|
+
module Format
|
|
8
|
+
class Regexp < Rule
|
|
9
|
+
|
|
10
|
+
include Format
|
|
11
|
+
|
|
12
|
+
equalize_on *(superclass.equalizer.keys + [:format, :format_name])
|
|
13
|
+
|
|
14
|
+
attr_reader :format_name
|
|
15
|
+
|
|
16
|
+
def initialize(attribute_name, options = {})
|
|
17
|
+
super
|
|
18
|
+
|
|
19
|
+
@format_name = options.fetch(:format_name, nil)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def valid?(resource)
|
|
23
|
+
value = attribute_value(resource)
|
|
24
|
+
return true if skip?(value)
|
|
25
|
+
|
|
26
|
+
value ? value.to_s =~ self.format : false
|
|
27
|
+
rescue ::Encoding::CompatibilityError
|
|
28
|
+
# This is to work around a bug in jruby - see formats/email.rb
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# TODO: integrate format into error message key?
|
|
33
|
+
# def error_message_args
|
|
34
|
+
# if format_name.is_a?(Symbol)
|
|
35
|
+
# [ :"invalid_#{format_name}", attribute_name ]
|
|
36
|
+
# else
|
|
37
|
+
# [ :invalid, attribute_name ]
|
|
38
|
+
# end
|
|
39
|
+
# end
|
|
40
|
+
|
|
41
|
+
end # class Regexp
|
|
42
|
+
end # module Format
|
|
43
|
+
end # class Rule
|
|
44
|
+
end # module Aequitas
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Aequitas
|
|
4
|
+
class Rule
|
|
5
|
+
module Formats
|
|
6
|
+
|
|
7
|
+
# Almost RFC2822 (No attribution reference available).
|
|
8
|
+
#
|
|
9
|
+
# This differs in that it does not allow local domains (test@localhost).
|
|
10
|
+
# 99% of the time you do not want to allow these email addresses
|
|
11
|
+
# in a public web application.
|
|
12
|
+
EmailAddress = begin
|
|
13
|
+
if (RUBY_VERSION == '1.9.2' && RUBY_ENGINE == 'jruby' && JRUBY_VERSION <= '1.6.3') || RUBY_VERSION == '1.9.3'
|
|
14
|
+
# There is an obscure bug in jruby 1.6 that prevents matching
|
|
15
|
+
# on unicode properties here. Remove this logic branch once
|
|
16
|
+
# a stable jruby release fixes this.
|
|
17
|
+
#
|
|
18
|
+
# http://jira.codehaus.org/browse/JRUBY-5622
|
|
19
|
+
#
|
|
20
|
+
# There is a similar bug in preview releases of 1.9.3
|
|
21
|
+
#
|
|
22
|
+
# http://redmine.ruby-lang.org/issues/5126
|
|
23
|
+
letter = 'a-zA-Z'
|
|
24
|
+
else
|
|
25
|
+
letter = 'a-zA-Z\p{L}' # Changed from RFC2822 to include unicode chars
|
|
26
|
+
end
|
|
27
|
+
digit = '0-9'
|
|
28
|
+
atext = "[#{letter}#{digit}\!\#\$\%\&\'\*+\/\=\?\^\_\`\{\|\}\~\-]"
|
|
29
|
+
dot_atom_text = "#{atext}+([.]#{atext}*)+"
|
|
30
|
+
dot_atom = dot_atom_text
|
|
31
|
+
no_ws_ctl = '\x01-\x08\x11\x12\x14-\x1f\x7f'
|
|
32
|
+
qtext = "[^#{no_ws_ctl}\\x0d\\x22\\x5c]" # Non-whitespace, non-control character except for \ and "
|
|
33
|
+
text = '[\x01-\x09\x11\x12\x14-\x7f]'
|
|
34
|
+
quoted_pair = "(\\x5c#{text})"
|
|
35
|
+
qcontent = "(?:#{qtext}|#{quoted_pair})"
|
|
36
|
+
quoted_string = "[\"]#{qcontent}+[\"]"
|
|
37
|
+
atom = "#{atext}+"
|
|
38
|
+
word = "(?:#{atom}|#{quoted_string})"
|
|
39
|
+
obs_local_part = "#{word}([.]#{word})*"
|
|
40
|
+
local_part = "(?:#{dot_atom}|#{quoted_string}|#{obs_local_part})"
|
|
41
|
+
dtext = "[#{no_ws_ctl}\\x21-\\x5a\\x5e-\\x7e]"
|
|
42
|
+
dcontent = "(?:#{dtext}|#{quoted_pair})"
|
|
43
|
+
domain_literal = "\\[#{dcontent}+\\]"
|
|
44
|
+
obs_domain = "#{atom}([.]#{atom})+"
|
|
45
|
+
domain = "(?:#{dot_atom}|#{domain_literal}|#{obs_domain})"
|
|
46
|
+
addr_spec = "#{local_part}\@#{domain}"
|
|
47
|
+
pattern = /\A#{addr_spec}\z/u
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end # module Formats
|
|
51
|
+
end # class Rule
|
|
52
|
+
end # module Aequitas
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Aequitas
|
|
4
|
+
class Rule
|
|
5
|
+
module Formats
|
|
6
|
+
|
|
7
|
+
# Regex from http://www.igvita.com/2006/09/07/validating-url-in-ruby-on-rails/
|
|
8
|
+
Url = begin
|
|
9
|
+
/(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}((\:[0-9]{1,5})?\/?.*)?$)/ix
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
end # module Formats
|
|
13
|
+
end # class Rule
|
|
14
|
+
end # module Aequitas
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/support/equalizable'
|
|
4
|
+
|
|
5
|
+
module Aequitas
|
|
6
|
+
class Rule
|
|
7
|
+
class Guard
|
|
8
|
+
extend Equalizable
|
|
9
|
+
|
|
10
|
+
equalize_on :if_test, :unless_test
|
|
11
|
+
|
|
12
|
+
attr_reader :if_test
|
|
13
|
+
attr_reader :unless_test
|
|
14
|
+
|
|
15
|
+
def initialize(options = {})
|
|
16
|
+
@if_test = options.fetch(:if, nil)
|
|
17
|
+
@unless_test = options.fetch(:unless, nil)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Determines if this RuleGuard allows the given resource
|
|
21
|
+
# by evaluating the if_test and unless_test
|
|
22
|
+
#
|
|
23
|
+
# @param [Object] resource
|
|
24
|
+
# The resource that we check against.
|
|
25
|
+
#
|
|
26
|
+
# @return [Boolean]
|
|
27
|
+
# true if allowed, otherwise false.
|
|
28
|
+
#
|
|
29
|
+
# @api private
|
|
30
|
+
def allow?(resource)
|
|
31
|
+
if if_test
|
|
32
|
+
!!evaluate_conditional_clause(resource, if_test)
|
|
33
|
+
elsif unless_test
|
|
34
|
+
!evaluate_conditional_clause(resource, unless_test)
|
|
35
|
+
else
|
|
36
|
+
true
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @api private
|
|
41
|
+
def evaluate_conditional_clause(resource, clause)
|
|
42
|
+
if clause.respond_to?(:call)
|
|
43
|
+
clause.call(resource)
|
|
44
|
+
elsif clause.kind_of?(Symbol)
|
|
45
|
+
resource.__send__(clause)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end # class Guard
|
|
50
|
+
end # class Rule
|
|
51
|
+
end # module Aequitas
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/rule'
|
|
4
|
+
|
|
5
|
+
module Aequitas
|
|
6
|
+
class Rule
|
|
7
|
+
module Length
|
|
8
|
+
|
|
9
|
+
# TODO: DRY this up (also implemented in Rule)
|
|
10
|
+
def self.rules_for(attribute_name, options)
|
|
11
|
+
Array(new(attribute_name, options))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# TODO: move options normalization into the validator macros
|
|
15
|
+
def self.new(attribute_name, options)
|
|
16
|
+
options = options.dup
|
|
17
|
+
|
|
18
|
+
equal = options.values_at(:is, :equals).compact.first
|
|
19
|
+
range = options.values_at(:in, :within).compact.first
|
|
20
|
+
minimum = options.values_at(:min, :minimum).compact.first
|
|
21
|
+
maximum = options.values_at(:max, :maximum).compact.first
|
|
22
|
+
|
|
23
|
+
if minimum && maximum
|
|
24
|
+
range ||= minimum..maximum
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if equal
|
|
28
|
+
Length::Equal.new(attribute_name, options.merge(:expected => equal))
|
|
29
|
+
elsif range
|
|
30
|
+
Length::Range.new(attribute_name, options.merge(:range => range))
|
|
31
|
+
elsif minimum
|
|
32
|
+
Length::Minimum.new(attribute_name, options.merge(:bound => minimum))
|
|
33
|
+
elsif maximum
|
|
34
|
+
Length::Maximum.new(attribute_name, options.merge(:bound => maximum))
|
|
35
|
+
else
|
|
36
|
+
# raise ArgumentError, "expected one of :is, :equals, :within, :in, :minimum, :min, :maximum, or :max; got #{options.keys.inspect}"
|
|
37
|
+
warn "expected length specification: one of :is, :equals, :in, :within, :min, :minimum, :max, or :maximum; got #{options.keys.inspect}"
|
|
38
|
+
Length::Dummy.new(attribute_name, options)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class Dummy < Rule
|
|
43
|
+
include Length
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def valid?(resource)
|
|
47
|
+
value = attribute_value(resource)
|
|
48
|
+
|
|
49
|
+
skip?(value) || valid_length?(value_length(value.to_s))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def valid_length?(length)
|
|
55
|
+
raise NotImplementedError, "#{self.class}#valid_length? must be implemented"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Return the length in characters
|
|
59
|
+
#
|
|
60
|
+
# @param [#to_str] value
|
|
61
|
+
# the string to get the number of characters for
|
|
62
|
+
#
|
|
63
|
+
# @return [Integer]
|
|
64
|
+
# the number of characters in the string
|
|
65
|
+
#
|
|
66
|
+
# @api private
|
|
67
|
+
def value_length(value)
|
|
68
|
+
value.to_str.length
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
if RUBY_VERSION < '1.9'
|
|
72
|
+
# calculate length of multi-byte-encoded strings
|
|
73
|
+
# as characters rather than bytes
|
|
74
|
+
def value_length(value)
|
|
75
|
+
value.to_str.scan(/./u).size
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end # module Length
|
|
80
|
+
end # class Rule
|
|
81
|
+
end # module Aequitas
|
|
82
|
+
|
|
83
|
+
# meh, I don't like doing this, but the superclass must be loaded before subclasses
|
|
84
|
+
require 'aequitas/rule/length/equal'
|
|
85
|
+
require 'aequitas/rule/length/range'
|
|
86
|
+
require 'aequitas/rule/length/minimum'
|
|
87
|
+
require 'aequitas/rule/length/maximum'
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/rule/length'
|
|
4
|
+
|
|
5
|
+
module Aequitas
|
|
6
|
+
class Rule
|
|
7
|
+
module Length
|
|
8
|
+
class Equal < Rule
|
|
9
|
+
|
|
10
|
+
include Length
|
|
11
|
+
|
|
12
|
+
attr_reader :expected
|
|
13
|
+
|
|
14
|
+
def initialize(attribute_name, options)
|
|
15
|
+
super
|
|
16
|
+
|
|
17
|
+
@expected = options.fetch(:expected)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def violation_type(resource)
|
|
21
|
+
:wrong_length
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def violation_data(resource)
|
|
25
|
+
[ [ :expected, expected ] ]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# Validate the value length is equal to the expected length
|
|
31
|
+
#
|
|
32
|
+
# @param [Integer] length
|
|
33
|
+
# the value length
|
|
34
|
+
#
|
|
35
|
+
# @return [String, nil]
|
|
36
|
+
# the error message if invalid, nil if not
|
|
37
|
+
#
|
|
38
|
+
# @api private
|
|
39
|
+
def valid_length?(length)
|
|
40
|
+
expected == length
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end # class Equal
|
|
44
|
+
end # module Length
|
|
45
|
+
end # class Rule
|
|
46
|
+
end # module Aequitas
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/rule/length'
|
|
4
|
+
|
|
5
|
+
module Aequitas
|
|
6
|
+
class Rule
|
|
7
|
+
module Length
|
|
8
|
+
class Maximum < Rule
|
|
9
|
+
|
|
10
|
+
include Length
|
|
11
|
+
|
|
12
|
+
attr_reader :bound
|
|
13
|
+
|
|
14
|
+
def initialize(attribute_name, options)
|
|
15
|
+
super
|
|
16
|
+
|
|
17
|
+
@bound = options.fetch(:bound)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def violation_type(resource)
|
|
21
|
+
:too_long
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def violation_data(resource)
|
|
25
|
+
[ [ :maximum, bound ] ]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# Validate the value length is less than or equal to the bound
|
|
31
|
+
#
|
|
32
|
+
# @param [Integer] length
|
|
33
|
+
# the value length
|
|
34
|
+
#
|
|
35
|
+
# @return [String, NilClass]
|
|
36
|
+
# the error message if invalid, nil if valid
|
|
37
|
+
#
|
|
38
|
+
# @api private
|
|
39
|
+
def valid_length?(length)
|
|
40
|
+
bound >= length
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end # class Maximum
|
|
44
|
+
end # module Length
|
|
45
|
+
end # class Rule
|
|
46
|
+
end # module Aequitas
|