lib/set_builder/modifier/base.rb in set_builder-2.0.0.beta2 vs lib/set_builder/modifier/base.rb in set_builder-2.0.0.beta3
- old
+ new
@@ -1,109 +1,116 @@
module SetBuilder
module Modifier
class Base
-
-
-
- def initialize(hash)
- @operator, @values = (hash.is_a?(Hash) ? [hash.first[0].to_sym, hash.first[1]] : [nil, nil])
- @values ||= []
- @values = [@values] unless @values.is_a?(Array)
- end
-
-
-
attr_reader :operator, :values
-
+
+
+
+ def initialize(params)
+ params.symbolize_keys!
+ @operator = params[:operator]
+ @operator = @operator.to_sym if @operator
+ @values = Array(params[:values])
+ end
+
+
+
def value
values[0]
end
-
-
-
+
+
+
def valid?
- valid_operator?(self.operator) && valid_arguments?(self.values)
+ errors.none?
end
-
-
-
- def valid_operator?(operator)
- !operator.nil? && self.class.operators.key?(operator)
+
+ def errors
+ [].tap do |errors|
+ errors.concat errors_with_operator
+ errors.concat errors_with_values
+ end
end
-
-
-
- def valid_arguments?(values)
- argument_types = self.class.operators[operator] || []
- return false unless (values.length == argument_types.length)
- values.each_with_index do |value, i|
- return false unless valid_argument_of_type?(value, argument_types[i])
+
+ def errors_with_operator
+ [].tap do |errors|
+ if operator.blank?
+ errors.push "operator is blank"
+ else
+ errors.push "#{operator.inspect} is not recognized. It should be #{self.class.operators.keys.map(&:inspect).to_sentence(two_words_connector: " or ", last_word_connector: ", or ")}" unless self.class.operators.key?(operator)
+ end
end
- true
end
-
-
-
- def valid_argument_of_type?(argument, type)
- validator = "valid_#{type}_argument?"
+
+ def errors_with_values
+ [].tap do |errors|
+ types = self.class.operators[operator] || []
+ if values.length != types.length
+ errors.push "wrong number of arguments; expected #{types.length} (#{types.join(", ")})"
+ else
+ errors.concat values.each_with_index.flat_map { |value, i| errors_with_value_type(value, types[i]) }
+ end
+ end
+ end
+
+ def errors_with_value_type(value, type)
+ validator = "errors_with_#{type}_value"
if respond_to?(validator)
- send(validator, argument)
+ Array(public_send(validator, value)).compact
else
- true
+ []
end
end
-
-
-
- def valid_date_argument?(string)
- begin
- Date.parse(string)
- true
- rescue
- false
- end
- end
- def valid_number_argument?(number)
- !(number.to_s =~ /\A\d+\Z/).nil?
+
+ def errors_with_date_value(string)
+ return "date is blank" if string.to_s.blank?
+ Date.parse(string.to_s)
+ nil
+ rescue
+ "#{string.inspect} is not a valid date"
end
-
-
-
+
+ def errors_with_number_value(string)
+ return "number is blank" if string.to_s.blank?
+ "#{string.inspect} is not a valid number" unless string.to_s =~ /\A\d+\Z/
+ end
+
+
+
def to_s(negative=false)
words = negative ? [self.class.negate(operator).to_s.gsub(/_/, " ")] : [operator.to_s.gsub(/_/, " ")]
arguments = self.class.operators[operator] || []
(0...arguments.length).each do |i|
- # p "ValueMap.to_s(#{arguments[i]} (#{arguments[i].class}), #{values[i]} (#{values[i].class})): #{ValueMap.to_s(arguments[i], values[i])}"
words << ValueMap.to_s(arguments[i], values[i])
end
words.join(" ")
end
-
-
-
+
+
+
def self.negate(operator)
operator
end
-
-
-
+
+
+
def self.to_hash
hash = {}
operators.each do |operator, array|
hash[operator.to_s] = array.map {|type| type.to_s }
end
hash
end
-
-
-
+
+
+
def self.to_json
to_hash.to_json
end
-
-
-
+
+
+
end
end
-end
\ No newline at end of file
+end