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.
Files changed (216) hide show
  1. data/.gitignore +4 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +6 -0
  4. data/LICENSE +21 -0
  5. data/README.rdoc +125 -0
  6. data/Rakefile +25 -0
  7. data/VERSION +1 -0
  8. data/aequitas.gemspec +20 -0
  9. data/lib/aequitas.rb +80 -0
  10. data/lib/aequitas/class_methods.rb +26 -0
  11. data/lib/aequitas/context.rb +53 -0
  12. data/lib/aequitas/contextual_rule_set.rb +221 -0
  13. data/lib/aequitas/exceptions.rb +10 -0
  14. data/lib/aequitas/macros.rb +466 -0
  15. data/lib/aequitas/message_transformer.rb +127 -0
  16. data/lib/aequitas/rule.rb +153 -0
  17. data/lib/aequitas/rule/absence.rb +14 -0
  18. data/lib/aequitas/rule/absence/blank.rb +21 -0
  19. data/lib/aequitas/rule/absence/nil.rb +21 -0
  20. data/lib/aequitas/rule/acceptance.rb +36 -0
  21. data/lib/aequitas/rule/block.rb +33 -0
  22. data/lib/aequitas/rule/confirmation.rb +41 -0
  23. data/lib/aequitas/rule/format.rb +81 -0
  24. data/lib/aequitas/rule/format/proc.rb +28 -0
  25. data/lib/aequitas/rule/format/regexp.rb +44 -0
  26. data/lib/aequitas/rule/formats/email.rb +52 -0
  27. data/lib/aequitas/rule/formats/url.rb +14 -0
  28. data/lib/aequitas/rule/guard.rb +51 -0
  29. data/lib/aequitas/rule/length.rb +87 -0
  30. data/lib/aequitas/rule/length/equal.rb +46 -0
  31. data/lib/aequitas/rule/length/maximum.rb +46 -0
  32. data/lib/aequitas/rule/length/minimum.rb +46 -0
  33. data/lib/aequitas/rule/length/range.rb +46 -0
  34. data/lib/aequitas/rule/method.rb +31 -0
  35. data/lib/aequitas/rule/numericalness.rb +85 -0
  36. data/lib/aequitas/rule/numericalness/equal.rb +30 -0
  37. data/lib/aequitas/rule/numericalness/greater_than.rb +30 -0
  38. data/lib/aequitas/rule/numericalness/greater_than_or_equal.rb +30 -0
  39. data/lib/aequitas/rule/numericalness/integer.rb +37 -0
  40. data/lib/aequitas/rule/numericalness/less_than.rb +30 -0
  41. data/lib/aequitas/rule/numericalness/less_than_or_equal.rb +30 -0
  42. data/lib/aequitas/rule/numericalness/non_integer.rb +64 -0
  43. data/lib/aequitas/rule/numericalness/not_equal.rb +30 -0
  44. data/lib/aequitas/rule/presence.rb +14 -0
  45. data/lib/aequitas/rule/presence/not_blank.rb +21 -0
  46. data/lib/aequitas/rule/presence/not_nil.rb +21 -0
  47. data/lib/aequitas/rule/primitive_type.rb +28 -0
  48. data/lib/aequitas/rule/skip_condition.rb +104 -0
  49. data/lib/aequitas/rule/within.rb +28 -0
  50. data/lib/aequitas/rule/within/range.rb +53 -0
  51. data/lib/aequitas/rule/within/range/bounded.rb +25 -0
  52. data/lib/aequitas/rule/within/range/unbounded_begin.rb +25 -0
  53. data/lib/aequitas/rule/within/range/unbounded_end.rb +25 -0
  54. data/lib/aequitas/rule/within/set.rb +39 -0
  55. data/lib/aequitas/rule_set.rb +80 -0
  56. data/lib/aequitas/support/blank.rb +22 -0
  57. data/lib/aequitas/support/equalizable.rb +113 -0
  58. data/lib/aequitas/support/ordered_hash.rb +438 -0
  59. data/lib/aequitas/version.rb +5 -0
  60. data/lib/aequitas/violation.rb +116 -0
  61. data/lib/aequitas/violation_set.rb +123 -0
  62. data/lib/aequitas/virtus.rb +29 -0
  63. data/lib/aequitas/virtus/inline_attribute_rule_extractor.rb +41 -0
  64. data/lib/aequitas/virtus/inline_attribute_rule_extractor/boolean.rb +17 -0
  65. data/lib/aequitas/virtus/inline_attribute_rule_extractor/object.rb +25 -0
  66. data/lib/aequitas/virtus/inline_attribute_rule_extractor/string.rb +27 -0
  67. data/spec/integration/aequitas/macros/validates_absence_of_spec.rb +19 -0
  68. data/spec/integration/aequitas/macros/validates_acceptance_of_spec.rb +19 -0
  69. data/spec/integration/aequitas/macros/validates_confirmation_of_spec.rb +25 -0
  70. data/spec/integration/aequitas/macros/validates_format_of_spec.rb +87 -0
  71. data/spec/integration/aequitas/macros/validates_length_of.rb +77 -0
  72. data/spec/integration/aequitas/macros/validates_numericalness_of_spec.rb +221 -0
  73. data/spec/integration/aequitas/macros/validates_presence_of_spec.rb +19 -0
  74. data/spec/integration/aequitas/macros/validates_with_block.rb +23 -0
  75. data/spec/integration/aequitas/macros/validates_with_method.rb +19 -0
  76. data/spec/integration/aequitas/macros/validates_within.rb +87 -0
  77. data/spec/integration/shared/macros/integration_spec.rb +67 -0
  78. data/spec/integration/virtus/boolean/presence_spec.rb +49 -0
  79. data/spec/integration/virtus/string/format/email_address_spec.rb +55 -0
  80. data/spec/integration/virtus/string/format/regexp_spec.rb +55 -0
  81. data/spec/integration/virtus/string/format/url_spec.rb +55 -0
  82. data/spec/integration/virtus/string/length/equal_spec.rb +49 -0
  83. data/spec/integration/virtus/string/length/range_spec.rb +49 -0
  84. data/spec/integration/virtus/string/presence_spec.rb +49 -0
  85. data/spec/rcov.opts +6 -0
  86. data/spec/spec_helper.rb +5 -0
  87. data/spec/suite.rb +5 -0
  88. data/spec/unit/aequitas/rule/absence/blank_spec.rb +45 -0
  89. data/spec/unit/aequitas/rule/acceptance_spec.rb +71 -0
  90. data/spec/unit/aequitas/rule/confirmation_spec.rb +80 -0
  91. data/spec/unit/aequitas/rule/guard_spec.rb +120 -0
  92. data/spec/unit/aequitas/rule/skip_condition_spec.rb +170 -0
  93. data/spec/unit/aequitas/rule_spec.rb +40 -0
  94. data/spec/unit/aequitas/support/blank_spec.rb +83 -0
  95. data/spec/unit/aequitas/support/equalizable/equalizer_spec.rb +21 -0
  96. data/spec/unit/aequitas/support/equalizable_spec.rb +67 -0
  97. data/spec/unit/aequitas/violation_set_spec.rb +154 -0
  98. data/spec_legacy/fixtures/barcode.rb +40 -0
  99. data/spec_legacy/fixtures/basketball_court.rb +58 -0
  100. data/spec_legacy/fixtures/basketball_player.rb +34 -0
  101. data/spec_legacy/fixtures/beta_tester_account.rb +33 -0
  102. data/spec_legacy/fixtures/bill_of_landing.rb +47 -0
  103. data/spec_legacy/fixtures/boat_dock.rb +26 -0
  104. data/spec_legacy/fixtures/city.rb +24 -0
  105. data/spec_legacy/fixtures/company.rb +93 -0
  106. data/spec_legacy/fixtures/corporate_world.rb +39 -0
  107. data/spec_legacy/fixtures/country.rb +24 -0
  108. data/spec_legacy/fixtures/ethernet_frame.rb +56 -0
  109. data/spec_legacy/fixtures/event.rb +44 -0
  110. data/spec_legacy/fixtures/g3_concert.rb +57 -0
  111. data/spec_legacy/fixtures/jabberwock.rb +27 -0
  112. data/spec_legacy/fixtures/kayak.rb +28 -0
  113. data/spec_legacy/fixtures/lernean_hydra.rb +39 -0
  114. data/spec_legacy/fixtures/llama_spaceship.rb +15 -0
  115. data/spec_legacy/fixtures/mathematical_function.rb +34 -0
  116. data/spec_legacy/fixtures/memory_object.rb +30 -0
  117. data/spec_legacy/fixtures/mittelschnauzer.rb +39 -0
  118. data/spec_legacy/fixtures/motor_launch.rb +21 -0
  119. data/spec_legacy/fixtures/multibyte.rb +16 -0
  120. data/spec_legacy/fixtures/page.rb +32 -0
  121. data/spec_legacy/fixtures/phone_number.rb +28 -0
  122. data/spec_legacy/fixtures/pirogue.rb +28 -0
  123. data/spec_legacy/fixtures/programming_language.rb +83 -0
  124. data/spec_legacy/fixtures/reservation.rb +38 -0
  125. data/spec_legacy/fixtures/scm_operation.rb +56 -0
  126. data/spec_legacy/fixtures/sms_message.rb +22 -0
  127. data/spec_legacy/fixtures/udp_packet.rb +49 -0
  128. data/spec_legacy/integration/absent_field_validator/absent_field_validator_spec.rb +90 -0
  129. data/spec_legacy/integration/absent_field_validator/spec_helper.rb +7 -0
  130. data/spec_legacy/integration/acceptance_validator/acceptance_validator_spec.rb +196 -0
  131. data/spec_legacy/integration/acceptance_validator/spec_helper.rb +7 -0
  132. data/spec_legacy/integration/automatic_validation/custom_messages_for_inferred_validation_spec.rb +57 -0
  133. data/spec_legacy/integration/automatic_validation/disabling_inferred_validation_spec.rb +49 -0
  134. data/spec_legacy/integration/automatic_validation/inferred_boolean_properties_validation_spec.rb +100 -0
  135. data/spec_legacy/integration/automatic_validation/inferred_float_property_validation_spec.rb +45 -0
  136. data/spec_legacy/integration/automatic_validation/inferred_format_validation_spec.rb +35 -0
  137. data/spec_legacy/integration/automatic_validation/inferred_integer_properties_validation_spec.rb +70 -0
  138. data/spec_legacy/integration/automatic_validation/inferred_length_validation_spec.rb +142 -0
  139. data/spec_legacy/integration/automatic_validation/inferred_presence_validation_spec.rb +45 -0
  140. data/spec_legacy/integration/automatic_validation/inferred_primitive_validation_spec.rb +22 -0
  141. data/spec_legacy/integration/automatic_validation/inferred_uniqueness_validation_spec.rb +48 -0
  142. data/spec_legacy/integration/automatic_validation/inferred_within_validation_spec.rb +35 -0
  143. data/spec_legacy/integration/automatic_validation/spec_helper.rb +57 -0
  144. data/spec_legacy/integration/block_validator/block_validator_spec.rb +32 -0
  145. data/spec_legacy/integration/block_validator/spec_helper.rb +5 -0
  146. data/spec_legacy/integration/conditional_validation/if_condition_spec.rb +63 -0
  147. data/spec_legacy/integration/conditional_validation/spec_helper.rb +5 -0
  148. data/spec_legacy/integration/confirmation_validator/confirmation_validator_spec.rb +76 -0
  149. data/spec_legacy/integration/confirmation_validator/spec_helper.rb +5 -0
  150. data/spec_legacy/integration/datamapper_models/association_validation_spec.rb +29 -0
  151. data/spec_legacy/integration/datamapper_models/inheritance_spec.rb +82 -0
  152. data/spec_legacy/integration/dirty_attributes/dirty_attributes_spec.rb +13 -0
  153. data/spec_legacy/integration/duplicated_validations/duplicated_validations_spec.rb +24 -0
  154. data/spec_legacy/integration/duplicated_validations/spec_helper.rb +5 -0
  155. data/spec_legacy/integration/format_validator/email_format_validator_spec.rb +139 -0
  156. data/spec_legacy/integration/format_validator/format_validator_spec.rb +64 -0
  157. data/spec_legacy/integration/format_validator/regexp_validator_spec.rb +33 -0
  158. data/spec_legacy/integration/format_validator/spec_helper.rb +5 -0
  159. data/spec_legacy/integration/format_validator/url_format_validator_spec.rb +93 -0
  160. data/spec_legacy/integration/length_validator/default_value_spec.rb +14 -0
  161. data/spec_legacy/integration/length_validator/equality_spec.rb +87 -0
  162. data/spec_legacy/integration/length_validator/error_message_spec.rb +22 -0
  163. data/spec_legacy/integration/length_validator/maximum_spec.rb +49 -0
  164. data/spec_legacy/integration/length_validator/minimum_spec.rb +54 -0
  165. data/spec_legacy/integration/length_validator/range_spec.rb +87 -0
  166. data/spec_legacy/integration/length_validator/spec_helper.rb +7 -0
  167. data/spec_legacy/integration/method_validator/method_validator_spec.rb +242 -0
  168. data/spec_legacy/integration/method_validator/spec_helper.rb +5 -0
  169. data/spec_legacy/integration/numeric_validator/equality_with_float_type_spec.rb +65 -0
  170. data/spec_legacy/integration/numeric_validator/equality_with_integer_type_spec.rb +41 -0
  171. data/spec_legacy/integration/numeric_validator/float_type_spec.rb +90 -0
  172. data/spec_legacy/integration/numeric_validator/gt_with_float_type_spec.rb +37 -0
  173. data/spec_legacy/integration/numeric_validator/gte_with_float_type_spec.rb +37 -0
  174. data/spec_legacy/integration/numeric_validator/integer_only_true_spec.rb +91 -0
  175. data/spec_legacy/integration/numeric_validator/integer_type_spec.rb +86 -0
  176. data/spec_legacy/integration/numeric_validator/lt_with_float_type_spec.rb +37 -0
  177. data/spec_legacy/integration/numeric_validator/lte_with_float_type_spec.rb +37 -0
  178. data/spec_legacy/integration/numeric_validator/spec_helper.rb +5 -0
  179. data/spec_legacy/integration/primitive_validator/primitive_validator_spec.rb +92 -0
  180. data/spec_legacy/integration/primitive_validator/spec_helper.rb +5 -0
  181. data/spec_legacy/integration/pure_ruby_objects/plain_old_ruby_object_validation_spec.rb +118 -0
  182. data/spec_legacy/integration/required_field_validator/association_spec.rb +69 -0
  183. data/spec_legacy/integration/required_field_validator/boolean_type_value_spec.rb +164 -0
  184. data/spec_legacy/integration/required_field_validator/date_type_value_spec.rb +127 -0
  185. data/spec_legacy/integration/required_field_validator/datetime_type_value_spec.rb +127 -0
  186. data/spec_legacy/integration/required_field_validator/float_type_value_spec.rb +131 -0
  187. data/spec_legacy/integration/required_field_validator/integer_type_value_spec.rb +99 -0
  188. data/spec_legacy/integration/required_field_validator/plain_old_ruby_object_spec.rb +35 -0
  189. data/spec_legacy/integration/required_field_validator/shared_examples.rb +26 -0
  190. data/spec_legacy/integration/required_field_validator/spec_helper.rb +7 -0
  191. data/spec_legacy/integration/required_field_validator/string_type_value_spec.rb +167 -0
  192. data/spec_legacy/integration/required_field_validator/text_type_value_spec.rb +49 -0
  193. data/spec_legacy/integration/shared/default_validation_context.rb +13 -0
  194. data/spec_legacy/integration/shared/valid_and_invalid_model.rb +35 -0
  195. data/spec_legacy/integration/uniqueness_validator/spec_helper.rb +5 -0
  196. data/spec_legacy/integration/uniqueness_validator/uniqueness_validator_spec.rb +116 -0
  197. data/spec_legacy/integration/within_validator/spec_helper.rb +5 -0
  198. data/spec_legacy/integration/within_validator/within_validator_spec.rb +168 -0
  199. data/spec_legacy/public/resource_spec.rb +105 -0
  200. data/spec_legacy/spec.opts +4 -0
  201. data/spec_legacy/spec_helper.rb +29 -0
  202. data/spec_legacy/unit/contextual_validators/emptiness_spec.rb +50 -0
  203. data/spec_legacy/unit/contextual_validators/execution_spec.rb +48 -0
  204. data/spec_legacy/unit/contextual_validators/spec_helper.rb +37 -0
  205. data/spec_legacy/unit/generic_validator/equality_operator_spec.rb +26 -0
  206. data/spec_legacy/unit/generic_validator/optional_spec.rb +54 -0
  207. data/spec_legacy/unit/validators/within_validator_spec.rb +23 -0
  208. data/spec_legacy/unit/violation_set/adding_spec.rb +54 -0
  209. data/spec_legacy/unit/violation_set/emptiness_spec.rb +38 -0
  210. data/spec_legacy/unit/violation_set/enumerable_spec.rb +32 -0
  211. data/spec_legacy/unit/violation_set/reading_spec.rb +35 -0
  212. data/spec_legacy/unit/violation_set/respond_to_spec.rb +15 -0
  213. data/tasks/spec.rake +38 -0
  214. data/tasks/yard.rake +9 -0
  215. data/tasks/yardstick.rake +19 -0
  216. metadata +302 -0
@@ -0,0 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Aequitas
4
+ VERSION = "0.0.1"
5
+ end
@@ -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