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,127 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Aequitas
4
+ # Transforms Violations to error message strings.
5
+ #
6
+ # @abstract
7
+ # Subclass and override {#transform} to implement a custom message
8
+ # transformer. Use {Violation.message_transformer=} to set a new
9
+ # message transformer or pass the transformer to {Violation#message}.
10
+ class MessageTransformer
11
+ def self.default
12
+ defined?(I18n) ? DefaultI18n.new : Default.new
13
+ end
14
+
15
+ # Transforms the specified Violation to an error message string.
16
+ #
17
+ # @param [Violation] violation
18
+ # The Violation to transform.
19
+ #
20
+ # @return [String]
21
+ # The transformed message.
22
+ #
23
+ # @raise [ArgumentError]
24
+ # +violation+ is +nil+.
25
+ def transform(violation)
26
+ raise NotImplementedError, "#{self.class}#transform has not been implemented"
27
+ end
28
+
29
+ class Default < self
30
+ @error_messages = {
31
+ :nil => '%s must not be nil',
32
+ :blank => '%s must not be blank',
33
+ :not_nil => '%s must be nil',
34
+ :not_blank => '%s must be blank',
35
+ :invalid => '%s has an invalid format',
36
+ :inclusion => '%s must be one of %s',
37
+ :accepted => '%s is not accepted',
38
+ :confirmation => '%s does not match the confirmation',
39
+ :length_between => '%s must be between %s and %s characters long',
40
+ :too_long => '%s must be at most %s characters long',
41
+ :too_short => '%s must be at least %s characters long',
42
+ :wrong_length => '%s must be %s characters long',
43
+ :not_a_number => '%s must be a number',
44
+ :not_an_integer => '%s must be an integer',
45
+ :greater_than => '%s must be greater than %s',
46
+ :greater_than_or_equal_to => '%s must be greater than or equal to %s',
47
+ :equal_to => '%s must be equal to %s',
48
+ :not_equal_to => '%s must not be equal to %s',
49
+ :less_than => '%s must be less than %s',
50
+ :less_than_or_equal_to => '%s must be less than or equal to %s',
51
+ :value_between => '%s must be between %s and %s',
52
+ :not_unique => '%s is already taken',
53
+ :primitive => '%s must be of type %s'
54
+ }
55
+
56
+ class << self
57
+ # Gets the hash of error messages used to transform violations.
58
+ #
59
+ # @return [Hash{Symbol=>String}]
60
+ attr_reader :error_messages
61
+ end
62
+
63
+ # Merges the specified +error_messages+ hash into the internal hash of
64
+ # error messages.
65
+ #
66
+ # @param [Hash{Symbol=>String}] error_messages
67
+ # The error messages to be merged.
68
+ def self.error_messages=(error_messages)
69
+ unless error_messages.is_a?(Hash)
70
+ raise ArgumentError, "+error_messages+ must be a hash"
71
+ end
72
+
73
+ self.error_messages.merge!(error_messages)
74
+ end
75
+
76
+ def self.error_message(violation_type, attribute_name, violation_values)
77
+ if message = self.error_messages[violation_type]
78
+ attribute_name = DataMapper::Inflector.humanize(attribute_name)
79
+ message % [attribute_name, *violation_values].flatten
80
+ else
81
+ violation_type.to_s
82
+ end
83
+ end
84
+
85
+ def transform(violation)
86
+ raise ArgumentError, "+violation+ must be specified" if violation.nil?
87
+
88
+ attribute_name = violation.attribute_name
89
+
90
+ self.class.error_message(violation.type, attribute_name, violation.values)
91
+ end
92
+ end # class Default
93
+
94
+ class DefaultI18n < self
95
+ def initialize
96
+ require 'i18n'
97
+ end
98
+
99
+ def transform(violation)
100
+ raise ArgumentError, "+violation+ must be specified" if violation.nil?
101
+
102
+ resource = violation.resource
103
+ model_name = resource.model.model_name
104
+ attribute_name = violation.attribute_name
105
+ # TODO: Include attribute value in Violation; it may have changed by now
106
+ # attribute_value = violation.attribute_value
107
+
108
+ options = {
109
+ :model => ::I18n.translate("models.#{model_name}"),
110
+ :attribute => ::I18n.translate("attributes.#{model_name}.#{attribute_name}"),
111
+ # TODO: Include attribute value in Violation; it may have changed by now
112
+ :value => resource.validation_attribute_value(attribute_name)
113
+ }.merge(violation.info)
114
+
115
+ ::I18n.translate("#{i18n_namespace}.#{violation.type}", options)
116
+ end
117
+
118
+ # configure the I18n namespace used for looking up error message text
119
+ attr_writer :i18n_namespace
120
+
121
+ def i18n_namespace
122
+ @i18n_namespace || 'aequitas.validation.errors'
123
+ end
124
+ end # class DefaultI18n
125
+
126
+ end # class MessageTransformer
127
+ end # module Aequitas
@@ -0,0 +1,153 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'aequitas/support/blank'
4
+ require 'aequitas/support/equalizable'
5
+ require 'aequitas/rule/guard'
6
+ require 'aequitas/rule/skip_condition'
7
+ require 'aequitas/violation'
8
+
9
+ module Aequitas
10
+ class Rule
11
+ extend Equalizable
12
+
13
+ equalize_on :attribute_name, :custom_message, :guard, :skip_condition
14
+
15
+ # @api private
16
+ attr_reader :attribute_name
17
+ # @api private
18
+ attr_reader :custom_message
19
+ # @api private
20
+ attr_reader :guard
21
+ # @api private
22
+ attr_reader :skip_condition
23
+
24
+ # Get the validators for the given attribute_name and options
25
+ #
26
+ # @param [Symbol] attribute_name
27
+ # the name of the attribute to which the returned validators will be bound
28
+ # @param [Hash] options
29
+ # the options with which to configure the returned validators
30
+ #
31
+ # @return [#each(Rule)]
32
+ # a collection of validators which collectively
33
+ #
34
+ def self.rules_for(attribute_name, options, &block)
35
+ Array(new(attribute_name, options, &block))
36
+ end
37
+
38
+ # Construct a validator. Capture the :if and :unless clauses when
39
+ # present.
40
+ #
41
+ # @param [String, Symbol] attribute_name
42
+ # The name of the attribute to validate.
43
+ #
44
+ # TODO: remove Hash as a value for :message
45
+ # (see Violation#[] in backwards.rb)
46
+ #
47
+ # @option [String, Hash] :message
48
+ # A custom message that will be used for any violations of this rule
49
+ # @option [Symbol, Proc] :if
50
+ # The name of a method (on the valiated resource) or a Proc to call
51
+ # (with the resource) to determine if the rule should be applied.
52
+ # @option [Symbol, Proc] :unless
53
+ # The name of a method (on the valiated resource) or a Proc to call
54
+ # (with the resource) to determine if the rule should *not* be applied.
55
+ # @option [Boolean] :allow_nil
56
+ # Whether to skip applying this rule on nil values
57
+ # @option [Boolean] :allow_blank
58
+ # Whether to skip applying this rule on blank values
59
+ def initialize(attribute_name, options = {})
60
+ @attribute_name = attribute_name
61
+ @custom_message = options.fetch(:message, nil)
62
+ @guard = options.fetch(:guard) { Guard.new(options) }
63
+ @skip_condition = options.fetch(:skip_condition) { SkipCondition.new(options) }
64
+ end
65
+
66
+ # Validate the +resource+ arg against this Rule
67
+ #
68
+ # @param [Object] resource
69
+ # the target object to be validated
70
+ #
71
+ # @return [NilClass, Violation]
72
+ # NilClass if +resource+ is valid
73
+ # Violation with additional info if +resource+ is invalid
74
+ def validate(resource)
75
+ if valid?(resource)
76
+ nil
77
+ else
78
+ Violation.new(resource, custom_message, self)
79
+ end
80
+ end
81
+
82
+ # Determines if this validator should be run against the resource
83
+ # by delegating to the guard configured for this rule
84
+ def execute?(resource)
85
+ guard.allow?(resource)
86
+ end
87
+
88
+ # Test the value to see if it is blank or nil, and if it is allowed.
89
+ # Note that allowing blank without explicitly denying nil allows nil
90
+ # values, since nil.blank? is true.
91
+ #
92
+ # @param [Object] value
93
+ # The value to test.
94
+ #
95
+ # @return [Boolean]
96
+ # true if blank/nil is allowed, and the value is blank/nil.
97
+ #
98
+ # @api private
99
+ def skip?(value)
100
+ skip_condition.skip?(value)
101
+ end
102
+
103
+ def attribute_value(resource)
104
+ resource.validation_attribute_value(attribute_name)
105
+ end
106
+
107
+ # @api private
108
+ def violation_info(resource)
109
+ Hash[ violation_data(resource) ]
110
+ end
111
+
112
+ # @api private
113
+ def violation_values(resource)
114
+ violation_data(resource).map { |(_, value)| value }
115
+ end
116
+
117
+ # @api private
118
+ def violation_data(resource)
119
+ [ ]
120
+ end
121
+
122
+ alias_method :to_s, :inspect
123
+
124
+ private
125
+
126
+ # def allow_nil!
127
+ # @allow_nil = true
128
+ # end
129
+
130
+ # def allow_blank!
131
+ # @allow_blank = true
132
+ # end
133
+
134
+ # Get the corresponding Resource property, if it exists.
135
+ #
136
+ # Note: DataMapper validations can be used on non-DataMapper resources.
137
+ # In such cases, the return value will be nil.
138
+ #
139
+ # @api private
140
+ def get_resource_property(resource, property_name)
141
+ model = resource.model if resource.respond_to?(:model)
142
+ repository = resource.repository if model
143
+ properties = model.properties(repository.name) if model
144
+ properties[property_name] if properties
145
+ end
146
+
147
+ def assert_kind_of(name, value, *klasses)
148
+ klasses.each { |k| return if value.kind_of?(k) }
149
+ raise ArgumentError, "+#{name}+ should be #{klasses.map { |k| k.name } * ' or '}, but was #{value.class.name}", caller(2)
150
+ end
151
+
152
+ end # class Rule
153
+ end # module Aequitas
@@ -0,0 +1,14 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'aequitas/rule'
4
+
5
+ module Aequitas
6
+ class Rule
7
+ class Absence < Rule
8
+
9
+ end # class Absence
10
+ end # class Rule
11
+ end # module Aequitas
12
+
13
+ require 'aequitas/rule/absence/blank'
14
+ require 'aequitas/rule/absence/nil'
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'aequitas/rule/absence'
4
+
5
+ module Aequitas
6
+ class Rule
7
+ class Absence
8
+ class Blank < Absence
9
+
10
+ def valid?(resource)
11
+ Aequitas.blank?(attribute_value(resource))
12
+ end
13
+
14
+ def violation_type(resource)
15
+ :not_blank
16
+ end
17
+
18
+ end # class Blank
19
+ end # class Absence
20
+ end # class Rule
21
+ end # module Aequitas
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'aequitas/rule/absence'
4
+
5
+ module Aequitas
6
+ class Rule
7
+ class Absence
8
+ class Nil < Absence
9
+
10
+ def valid?(resource)
11
+ attribute_value(resource).nil?
12
+ end
13
+
14
+ def violation_type(resource)
15
+ :not_nil
16
+ end
17
+
18
+ end # class Nil
19
+ end # class Absence
20
+ end # class Rule
21
+ end # module Aequitas
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'aequitas/rule'
4
+
5
+ module Aequitas
6
+ class Rule
7
+ # TODO: update this to inherit from Rule::Within::Set
8
+ class Acceptance < Rule
9
+
10
+ equalize_on *(superclass.equalizer.keys + [:accept])
11
+
12
+ DEFAULT_ACCEPTED_VALUES = [ '1', 1, 'true', true, 't' ]
13
+
14
+ attr_reader :accept
15
+
16
+ def initialize(attribute_name, options = {})
17
+ super
18
+
19
+ @accept = Array(options.fetch(:accept, DEFAULT_ACCEPTED_VALUES))
20
+
21
+ skip_condition.default_to_allowing_nil!
22
+ end
23
+
24
+ def valid?(resource)
25
+ value = attribute_value(resource)
26
+
27
+ skip?(value) || accept.include?(value)
28
+ end
29
+
30
+ def violation_type(resource)
31
+ :accepted
32
+ end
33
+
34
+ end # class Acceptance
35
+ end # class Rule
36
+ end # module Aequitas
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'aequitas/rule'
4
+
5
+ module Aequitas
6
+ class Rule
7
+ class Block < Rule
8
+
9
+ attr_reader :block
10
+
11
+ def initialize(attribute_name, options, &block)
12
+ unless block_given?
13
+ raise ArgumentError, 'cannot initialize a Block validator without a block'
14
+ end
15
+
16
+ super
17
+
18
+ @block = block
19
+ end
20
+
21
+ def validate(resource)
22
+ result, error_message = resource.instance_eval(&self.block)
23
+
24
+ if result
25
+ nil
26
+ else
27
+ Violation.new(resource, error_message, self)
28
+ end
29
+ end
30
+
31
+ end # class Block
32
+ end # class Rule
33
+ end # module Aequitas
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'aequitas/rule'
4
+
5
+ module Aequitas
6
+ class Rule
7
+ class Confirmation < Rule
8
+
9
+ equalize_on *(superclass.equalizer.keys + [:confirmation_attribute_name])
10
+
11
+ attr_reader :confirmation_attribute_name
12
+
13
+
14
+ def initialize(attribute_name, options = {})
15
+ super
16
+
17
+ @confirmation_attribute_name = options.fetch(:confirm) do
18
+ :"#{attribute_name}_confirmation"
19
+ end
20
+
21
+ skip_condition.default_to_allowing_nil!
22
+ skip_condition.default_to_allowing_blank!
23
+ end
24
+
25
+ def valid?(resource)
26
+ value = attribute_value(resource)
27
+
28
+ skip?(value) || value == confirmation_value(resource)
29
+ end
30
+
31
+ def confirmation_value(resource)
32
+ resource.instance_variable_get("@#{@confirmation_attribute_name}")
33
+ end
34
+
35
+ def violation_type(resource)
36
+ :confirmation
37
+ end
38
+
39
+ end # class Confirmation
40
+ end # class Rule
41
+ end # module Aequitas