PageRenderTime 52ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/gems/carlosbrando-remarkable-2.2.4/lib/remarkable/active_record/macros/validations/validate_numericality_of_matcher.rb

https://github.com/qoobaa/sms
Ruby | 214 lines | 124 code | 38 blank | 52 comment | 23 complexity | 545913560a30482df234fedbe6b3ff32 MD5 | raw file
  1. module Remarkable # :nodoc:
  2. module ActiveRecord # :nodoc:
  3. module Matchers # :nodoc:
  4. class ValidateNumericalityOfMatcher < Remarkable::Matcher::Base
  5. include Remarkable::ActiveRecord::Helpers
  6. NUMERIC_COMPARISIONS = [:equal_to, :less_than, :greater_than, :less_than_or_equal_to, :greater_than_or_equal_to]
  7. arguments :attributes
  8. optional :only_integer, :odd, :even, :default => true
  9. optional :equal_to, :less_than, :greater_than, :less_than_or_equal_to, :greater_than_or_equal_to
  10. assertions :only_allow_numeric_values?, :allow_blank?, :allow_nil?,
  11. :only_integer?, :allow_odd?, :allow_even?, :equal_to_for_each_option?,
  12. :less_than_maximum_for_each_option?, :more_than_maximum_for_each_option?
  13. def description
  14. default_message + "for #{@attributes.to_sentence}"
  15. end
  16. private
  17. # Check equal_to? for each given option
  18. #
  19. def equal_to_for_each_option?
  20. equal_to?(:equal_to) && equal_to?(:less_than, -1) && equal_to?(:greater_than, +1) &&
  21. equal_to?(:less_than_or_equal_to) && equal_to?(:greater_than_or_equal_to)
  22. end
  23. # Check more_than_maximum? for each given option
  24. #
  25. def more_than_maximum_for_each_option?
  26. more_than_maximum?(:equal_to, +1) && more_than_maximum?(:less_than) &&
  27. more_than_maximum?(:less_than_or_equal_to, +1)
  28. end
  29. # Check less_than_maximum? for each given option
  30. #
  31. def less_than_maximum_for_each_option?
  32. less_than_minimum?(:equal_to, -1) && less_than_minimum?(:greater_than) &&
  33. less_than_minimum?(:greater_than_or_equal_to, -1)
  34. end
  35. def only_allow_numeric_values?
  36. return true if bad?("abcd")
  37. @missing = "allow non-numeric values for #{@attribute}"
  38. false
  39. end
  40. def only_integer?
  41. message = "allow non-integer values for #{@attribute}"
  42. assert_bad_or_good_if_key(:only_integer, valid_value_for_test.to_f, message, :message)
  43. end
  44. def allow_even?
  45. message = "allow even values for #{@attribute}"
  46. assert_bad_or_good_if_key(:even, valid_value_for_test + 1, message, default_message_for(:even))
  47. end
  48. def allow_odd?
  49. message = "allow odd values for #{@attribute}"
  50. assert_bad_or_good_if_key(:odd, even_valid_value_for_test, message, default_message_for(:odd))
  51. end
  52. def equal_to?(key, add = 0)
  53. return true unless @options.key?(key)
  54. return true if good?(@options[key] + add, default_message_for(key), @options[key])
  55. @missing = "did not allow value equals to #{@options[key]} for #{@attribute}"
  56. false
  57. end
  58. def more_than_maximum?(key, add = 0)
  59. return true unless @options.key?(key)
  60. return true if bad?(@options[key] + add, default_message_for(key), @options[key])
  61. # We should do @options[key] + add - 1 to adjust messages in less_than cases.
  62. @missing = "allowed value #{@options[key] + add} which is more than #{@options[key] + add - 1} for #{@attribute}"
  63. false
  64. end
  65. def less_than_minimum?(key, add = 0)
  66. return true unless @options.key?(key)
  67. return true if bad?(@options[key] + add, default_message_for(key), @options[key])
  68. # We should do @options[key] + add + 1 to adjust messages in greater_than cases.
  69. @missing = "allowed value #{@options[key] + add} which is less than #{@options[key] + add + 1} for #{@attribute}"
  70. false
  71. end
  72. # Returns a valid value for test.
  73. #
  74. def valid_value_for_test
  75. value = @options[:equal_to] || @options[:less_than_or_equal_to] || @options[:greater_than_or_equal_to]
  76. value ||= @options[:less_than] - 1 if @options[:less_than]
  77. value ||= @options[:greater_than] + 1 if @options[:greater_than]
  78. value ||= 10
  79. if @options[:even]
  80. value = (value / 2) * 2
  81. elsif @options[:odd]
  82. value = ((value / 2) * 2) + 1
  83. end
  84. value
  85. end
  86. # Returns a valid even value for test.
  87. # The method valid_value_for_test checks for :even option but does not
  88. # return necessarily an even value
  89. #
  90. def even_valid_value_for_test
  91. (valid_value_for_test / 2) * 2
  92. end
  93. def default_options
  94. options = {
  95. :message => :not_a_number,
  96. :odd_message => :odd,
  97. :even_message => :even
  98. }
  99. NUMERIC_COMPARISIONS.each do |key|
  100. options[:"#{key}_message"] = key
  101. end
  102. options
  103. end
  104. # Returns the default message for each key (:odd, :even, :equal_to, ...).
  105. # If the main :message is equal :not_a_number, it means the user changed
  106. # it so we should use it. Otherwise returns :odd_message, :even_message
  107. # and so on.
  108. #
  109. def default_message_for(key)
  110. @options[:message] == :not_a_number ? :"#{key}_message" : :message
  111. end
  112. def expectation
  113. default_message + "for #{@attribute}"
  114. end
  115. def default_message
  116. message = "only allow "
  117. message << "even " if @options[:even]
  118. message << "odd " if @options[:odd]
  119. message << (@options[:only_integer] ? "integer values " : "numeric values ")
  120. message << NUMERIC_COMPARISIONS.map do |key|
  121. @options[key] ? "#{key.to_s.gsub('_', ' ')} #{@options[key]} " : nil
  122. end.compact.join('or ')
  123. message << "or nil " if @options[:allow_nil]
  124. message << "or blank " if @options[:allow_blank]
  125. message
  126. end
  127. end
  128. # Ensures that the given attributes accepts only numbers.
  129. #
  130. # If an instance variable has been created in the setup named after the
  131. # model being tested, then this method will use that. Otherwise, it will
  132. # create a new instance to test against.
  133. #
  134. # Options:
  135. #
  136. # * <tt>:only_integer</tt> - when supplied, checks if it accepts only integers or not
  137. # * <tt>:odd</tt> - when supplied, checks if it accepts only odd values or not
  138. # * <tt>:even</tt> - when supplied, checks if it accepts only even values or not
  139. # * <tt>:equal_to</tt> - when supplied, checks if attributes are only valid when equal to given value
  140. # * <tt>:less_than</tt> - when supplied, checks if attributes are only valid when less than given value
  141. # * <tt>:greater_than</tt> - when supplied, checks if attributes are only valid when greater than given value
  142. # * <tt>:less_than_or_equal_to</tt> - when supplied, checks if attributes are only valid when less than or equal to given value
  143. # * <tt>:greater_than_or_equal_to</tt> - when supplied, checks if attributes are only valid when greater than or equal to given value
  144. # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
  145. # Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.not_a_number')</tt>
  146. #
  147. # Example:
  148. #
  149. # it { should validate_numericality_of(:age, :price) }
  150. # it { should validate_numericality_of(:age, :only_integer => true) }
  151. # it { should validate_numericality_of(:price, :only_integer => false) }
  152. # it { should validate_numericality_of(:age).only_integer }
  153. #
  154. # it { should validate_numericality_of(:age).odd }
  155. # it { should validate_numericality_of(:age).even }
  156. # it { should validate_numericality_of(:age, :odd => true) }
  157. # it { should validate_numericality_of(:age, :even => true) }
  158. #
  159. def validate_numericality_of(*attributes)
  160. ValidateNumericalityOfMatcher.new(*attributes)
  161. end
  162. # TODO Deprecate me
  163. def only_allow_numeric_values_for(*attributes) #:nodoc:
  164. warn "[DEPRECATION] should_only_allow_numeric_values_for is deprecated. " <<
  165. "Use should_validate_numericality_of instead."
  166. ValidateNumericalityOfMatcher.new(*attributes)
  167. end
  168. # TODO Deprecate me
  169. def only_allow_numeric_or_blank_values_for(*attributes)
  170. warn "[DEPRECATION] should_only_allow_numeric_or_blank_values_for is deprecated. " <<
  171. "Use should_validate_numericality_of with :allow_blank => true instead."
  172. ValidateNumericalityOfMatcher.new(*attributes).allow_blank
  173. end
  174. end
  175. end
  176. end