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,116 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/exceptions'
|
|
4
|
+
require 'aequitas/support/equalizable'
|
|
5
|
+
require 'aequitas/message_transformer'
|
|
6
|
+
|
|
7
|
+
module Aequitas
|
|
8
|
+
class Violation
|
|
9
|
+
extend Aequitas::Equalizable
|
|
10
|
+
|
|
11
|
+
equalize_on :resource, :rule, :custom_message, :attribute_name
|
|
12
|
+
|
|
13
|
+
def self.default_transformer
|
|
14
|
+
@default_transformer ||= MessageTransformer.default
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.default_transformer=(transformer)
|
|
18
|
+
@default_transformer = transformer
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
attr_reader :resource
|
|
22
|
+
attr_reader :custom_message
|
|
23
|
+
attr_reader :rule
|
|
24
|
+
attr_reader :attribute_name
|
|
25
|
+
|
|
26
|
+
# Configure a Violation instance
|
|
27
|
+
#
|
|
28
|
+
# @param [Object] resource
|
|
29
|
+
# the validated object
|
|
30
|
+
# @param [String, #call, Hash] message
|
|
31
|
+
# an optional custom message for this Violation
|
|
32
|
+
# @param [Rule] rule
|
|
33
|
+
# the Rule whose violation triggered the creation of the receiver
|
|
34
|
+
# @param [Symbol] attribute_name
|
|
35
|
+
# the name of the attribute whose validation rule was violated
|
|
36
|
+
# or nil, if a Rule was provided.
|
|
37
|
+
#
|
|
38
|
+
def initialize(resource, message = nil, rule = nil, attribute_name = nil)
|
|
39
|
+
unless message || rule
|
|
40
|
+
raise ArgumentError, "expected +message+ or +rule+"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
@resource = resource
|
|
44
|
+
@rule = rule
|
|
45
|
+
@attribute_name = attribute_name
|
|
46
|
+
@custom_message = evaluate_message(message)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @api public
|
|
50
|
+
def message(transformer = Undefined)
|
|
51
|
+
return @custom_message if @custom_message
|
|
52
|
+
|
|
53
|
+
transformer = Undefined == transformer ? self.transformer : transformer
|
|
54
|
+
|
|
55
|
+
transformer.transform(self)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @api public
|
|
59
|
+
alias_method :to_s, :message
|
|
60
|
+
|
|
61
|
+
# @api public
|
|
62
|
+
def attribute_name
|
|
63
|
+
if @attribute_name
|
|
64
|
+
@attribute_name
|
|
65
|
+
elsif rule
|
|
66
|
+
rule.attribute_name
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @api public
|
|
71
|
+
def type
|
|
72
|
+
rule ? rule.violation_type(resource) : nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @api public
|
|
76
|
+
def info
|
|
77
|
+
rule ? rule.violation_info(resource) : { }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def values
|
|
81
|
+
rule ? rule.violation_values(resource) : [ ]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def transformer
|
|
85
|
+
if resource.respond_to?(:validation_rules) && transformer = resource.validation_rules.transformer
|
|
86
|
+
transformer
|
|
87
|
+
else
|
|
88
|
+
Violation.default_transformer
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def evaluate_message(message)
|
|
93
|
+
if message.respond_to?(:call)
|
|
94
|
+
if resource.respond_to?(:model) && resource.model.respond_to?(:properties)
|
|
95
|
+
property = resource.model.properties[attribute_name]
|
|
96
|
+
message.call(resource, property)
|
|
97
|
+
else
|
|
98
|
+
message.call(resource)
|
|
99
|
+
end
|
|
100
|
+
else
|
|
101
|
+
message
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# In general we want Aequitas::Equalizable-type equality/equivalence,
|
|
106
|
+
# but this allows direct equivalency test against Strings, which is handy
|
|
107
|
+
def ==(other)
|
|
108
|
+
if other.respond_to?(:to_str)
|
|
109
|
+
self.to_s == other.to_str
|
|
110
|
+
else
|
|
111
|
+
super
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end # class Violation
|
|
116
|
+
end # module Aequitas
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/support/blank'
|
|
4
|
+
require 'aequitas/support/ordered_hash'
|
|
5
|
+
require 'aequitas/violation'
|
|
6
|
+
|
|
7
|
+
module Aequitas
|
|
8
|
+
class ViolationSet
|
|
9
|
+
|
|
10
|
+
include Enumerable
|
|
11
|
+
|
|
12
|
+
# @api private
|
|
13
|
+
attr_reader :resource
|
|
14
|
+
|
|
15
|
+
# @api private
|
|
16
|
+
attr_reader :violations
|
|
17
|
+
# TODO: why was this private?
|
|
18
|
+
private :violations
|
|
19
|
+
|
|
20
|
+
# TODO: replace OrderedHash with OrderedSet and remove vendor'd OrderedHash
|
|
21
|
+
def initialize(resource)
|
|
22
|
+
@resource = resource
|
|
23
|
+
@violations = OrderedHash.new { |h,k| h[k] = [] }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Clear existing validation violations.
|
|
27
|
+
#
|
|
28
|
+
# @api public
|
|
29
|
+
def clear
|
|
30
|
+
violations.clear
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Add a validation error. Use the attribute_name :general if the violations
|
|
34
|
+
# does not apply to a specific field of the Resource.
|
|
35
|
+
#
|
|
36
|
+
# @param [Symbol, Violation] attribute_name_or_violation
|
|
37
|
+
# The name of the field that caused the violation, or
|
|
38
|
+
# the Violation which describes the validation violation
|
|
39
|
+
# @param [NilClass, String, #call, Hash] message
|
|
40
|
+
# The message to add.
|
|
41
|
+
#
|
|
42
|
+
# @see Violation#initialize
|
|
43
|
+
#
|
|
44
|
+
# @api public
|
|
45
|
+
def add(attribute_name_or_violation, message = nil)
|
|
46
|
+
violation =
|
|
47
|
+
if attribute_name_or_violation.kind_of?(Violation)
|
|
48
|
+
attribute_name_or_violation
|
|
49
|
+
else
|
|
50
|
+
# TODO: Violation.from_message(resource, message, attribute_name_or_violation)
|
|
51
|
+
Violation.new(resource, message, nil, attribute_name_or_violation)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
self << violation
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def <<(violation)
|
|
58
|
+
violations[violation.attribute_name] << violation
|
|
59
|
+
self
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def concat(other)
|
|
63
|
+
other.each { |violation| self << violation }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Collect all violations into a single list.
|
|
67
|
+
#
|
|
68
|
+
# @api public
|
|
69
|
+
def full_messages
|
|
70
|
+
violations.inject([]) do |list, (attribute_name, violations)|
|
|
71
|
+
messages = violations
|
|
72
|
+
messages = violations.full_messages if violations.respond_to?(:full_messages)
|
|
73
|
+
list.concat(messages)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Return validation violations for a particular attribute_name.
|
|
78
|
+
#
|
|
79
|
+
# @param [Symbol] attribute_name
|
|
80
|
+
# The name of the field you want an violation for.
|
|
81
|
+
#
|
|
82
|
+
# @return [Array(Violation, String), NilClass]
|
|
83
|
+
# Array of Violations, if there are violations on +attribute_name+
|
|
84
|
+
# nil if there are no violations on +attribute_name+
|
|
85
|
+
#
|
|
86
|
+
# @api public
|
|
87
|
+
#
|
|
88
|
+
# TODO: use a data structure that ensures uniqueness
|
|
89
|
+
def on(attribute_name)
|
|
90
|
+
attribute_violations = violations[attribute_name]
|
|
91
|
+
attribute_violations.empty? ? nil : attribute_violations.uniq
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# @api public
|
|
95
|
+
def each
|
|
96
|
+
violations.each_value do |v|
|
|
97
|
+
yield(v) unless Aequitas.blank?(v)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# @api public
|
|
102
|
+
def empty?
|
|
103
|
+
violations.all? { |_, violations| violations.empty? }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @api public
|
|
107
|
+
#
|
|
108
|
+
# FIXME: calling #to_sym on uncontrolled input is an
|
|
109
|
+
# invitation for a memory leak
|
|
110
|
+
def [](attribute_name)
|
|
111
|
+
violations[attribute_name.to_sym]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def method_missing(meth, *args, &block)
|
|
115
|
+
violations.send(meth, *args, &block)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def respond_to?(method)
|
|
119
|
+
super || violations.respond_to?(method)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end # class ViolationSet
|
|
123
|
+
end # module Aequitas
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'aequitas/virtus/inline_attribute_rule_extractor'
|
|
2
|
+
|
|
3
|
+
module Virtus
|
|
4
|
+
class Attribute
|
|
5
|
+
Object.accept_options :required# , :prohibited, :forbidden # hmm...
|
|
6
|
+
String.accept_options :length, :format
|
|
7
|
+
Decimal.accept_options :precision, :scale
|
|
8
|
+
Float.accept_options :precision, :scale
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module Aequitas
|
|
13
|
+
module ClassMethods
|
|
14
|
+
def self.extended(base)
|
|
15
|
+
super
|
|
16
|
+
base.extend Aequitas::Virtus::ClassMethodOverrides
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
module Virtus
|
|
21
|
+
module ClassMethodOverrides
|
|
22
|
+
def virtus_add_attribute(attribute)
|
|
23
|
+
super
|
|
24
|
+
inline_attribute_rules = InlineAttributeRuleExtractor.extract(attribute)
|
|
25
|
+
validation_rules.context(:default).concat(inline_attribute_rules)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Aequitas
|
|
2
|
+
module Virtus
|
|
3
|
+
class InlineAttributeRuleExtractor
|
|
4
|
+
|
|
5
|
+
def self.extract(attribute)
|
|
6
|
+
type =
|
|
7
|
+
case attribute
|
|
8
|
+
when ::Virtus::Attribute::Boolean; self::Boolean
|
|
9
|
+
when ::Virtus::Attribute::String; self::String
|
|
10
|
+
# when ::Virtus::Attribute::Decimal; self::Decimal
|
|
11
|
+
# when ::Virtus::Attribute::Float; self::Float
|
|
12
|
+
when ::Virtus::Attribute::Object; self::Object
|
|
13
|
+
end
|
|
14
|
+
type.new(attribute).extract
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attr_reader :attribute
|
|
18
|
+
|
|
19
|
+
def initialize(attribute)
|
|
20
|
+
@attribute = attribute
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def options
|
|
24
|
+
attribute.options
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def extract
|
|
28
|
+
rules = []
|
|
29
|
+
rules.concat Array(extract_presence_rules) if options.fetch(:required, false)
|
|
30
|
+
rules.concat Array(extract_length_rules) if options.fetch(:length, false)
|
|
31
|
+
rules.concat Array(extract_format_rules) if options.fetch(:format, false)
|
|
32
|
+
rules
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end # module Virtus
|
|
37
|
+
end # module Aequitas
|
|
38
|
+
|
|
39
|
+
require 'aequitas/virtus/inline_attribute_rule_extractor/object'
|
|
40
|
+
require 'aequitas/virtus/inline_attribute_rule_extractor/boolean'
|
|
41
|
+
require 'aequitas/virtus/inline_attribute_rule_extractor/string'
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/virtus/inline_attribute_rule_extractor/object'
|
|
4
|
+
|
|
5
|
+
module Aequitas
|
|
6
|
+
module Virtus
|
|
7
|
+
class InlineAttributeRuleExtractor
|
|
8
|
+
class Boolean < Object
|
|
9
|
+
|
|
10
|
+
def extract_presence_rules
|
|
11
|
+
Rule::Presence::NotNil.new(attribute.name)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end # class Boolean
|
|
15
|
+
end # class InlineAttributeRuleExtractor
|
|
16
|
+
end # module Virtus
|
|
17
|
+
end # module Aequitas
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/virtus/inline_attribute_rule_extractor'
|
|
4
|
+
|
|
5
|
+
module Aequitas
|
|
6
|
+
module Virtus
|
|
7
|
+
class InlineAttributeRuleExtractor
|
|
8
|
+
class Object < InlineAttributeRuleExtractor
|
|
9
|
+
|
|
10
|
+
def extract_presence_rules
|
|
11
|
+
Rule::Presence::NotBlank.new(attribute.name)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def extract_length_rules
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def extract_format_rules
|
|
19
|
+
nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end # class Object
|
|
23
|
+
end # class InlineAttributeRuleExtractor
|
|
24
|
+
end # module Virtus
|
|
25
|
+
end # module Aequitas
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'aequitas/virtus/inline_attribute_rule_extractor/object'
|
|
4
|
+
|
|
5
|
+
module Aequitas
|
|
6
|
+
module Virtus
|
|
7
|
+
class InlineAttributeRuleExtractor
|
|
8
|
+
class String < Object
|
|
9
|
+
|
|
10
|
+
def extract_length_rules
|
|
11
|
+
length = attribute.options.fetch(:length)
|
|
12
|
+
|
|
13
|
+
case length
|
|
14
|
+
when Integer; Rule::Length::Equal.new(attribute.name, :expected => length)
|
|
15
|
+
when Range; Rule::Length::Range.new(attribute.name, :range => length)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def extract_format_rules
|
|
20
|
+
format = attribute.options.fetch(:format)
|
|
21
|
+
Rule::Format.new(attribute.name, :with => format)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end # class String
|
|
25
|
+
end # class InlineAttributeRuleExtractor
|
|
26
|
+
end # module Virtus
|
|
27
|
+
end # module Aequitas
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require_relative '../../../spec_helper'
|
|
2
|
+
require_relative '../../shared/macros/integration_spec'
|
|
3
|
+
require 'aequitas'
|
|
4
|
+
|
|
5
|
+
Aequitas::Macros::IntegrationSpec.describe Aequitas::Macros, '#validates_absence_of' do
|
|
6
|
+
before { class_under_test.validates_absence_of attribute_name }
|
|
7
|
+
|
|
8
|
+
describe 'when validated attribute is present' do
|
|
9
|
+
let(:attribute_value) { :foo }
|
|
10
|
+
|
|
11
|
+
it_should_be_an_invalid_instance
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe 'when validated attribute is absent' do
|
|
15
|
+
let(:attribute_value) { nil }
|
|
16
|
+
|
|
17
|
+
it_should_be_a_valid_instance
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require_relative '../../../spec_helper'
|
|
2
|
+
require_relative '../../shared/macros/integration_spec'
|
|
3
|
+
require 'aequitas'
|
|
4
|
+
|
|
5
|
+
Aequitas::Macros::IntegrationSpec.describe Aequitas::Macros, '#validates_acceptance_of' do
|
|
6
|
+
before { class_under_test.validates_acceptance_of attribute_name }
|
|
7
|
+
|
|
8
|
+
describe 'when attribute value is accepted' do
|
|
9
|
+
let(:attribute_value) { true }
|
|
10
|
+
|
|
11
|
+
it_should_be_a_valid_instance
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe 'when attribute value is not accepted' do
|
|
15
|
+
let(:attribute_value) { false }
|
|
16
|
+
|
|
17
|
+
it_should_be_an_invalid_instance
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require_relative '../../../spec_helper'
|
|
2
|
+
require_relative '../../shared/macros/integration_spec'
|
|
3
|
+
require 'aequitas'
|
|
4
|
+
|
|
5
|
+
Aequitas::Macros::IntegrationSpec.describe Aequitas::Macros, '#validates_confirmation_of' do
|
|
6
|
+
before do
|
|
7
|
+
class_under_test.send(:attr_accessor, "#{attribute_name}_confirmation")
|
|
8
|
+
class_under_test.validates_confirmation_of attribute_name
|
|
9
|
+
subject.send("#{attribute_name}_confirmation=", confirmation_value)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe 'when confirmation value matches' do
|
|
13
|
+
let(:attribute_value) { :foo }
|
|
14
|
+
let(:confirmation_value) { :foo }
|
|
15
|
+
|
|
16
|
+
it_should_be_a_valid_instance
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe 'when confirmation value does not match' do
|
|
20
|
+
let(:attribute_value) { :foo }
|
|
21
|
+
let(:confirmation_value) { :bar }
|
|
22
|
+
|
|
23
|
+
it_should_be_an_invalid_instance
|
|
24
|
+
end
|
|
25
|
+
end
|