class Ransack::Nodes::Condition
def arel_predicate
def arel_predicate predicates = attributes.map do |attr| attr.attr.send(predicate.arel_predicate, formatted_values_for_attribute(attr)) end if predicates.size > 1 case combinator when 'and' Arel::Nodes::Grouping.new(Arel::Nodes::And.new(predicates)) when 'or' predicates.inject(&:or) end else predicates.first end end
def attributes
def attributes @attributes ||= [] end
def attributes=(args)
def attributes=(args) case args when Array args.each do |attr| attr = Attribute.new(@context, attr) self.attributes << attr if attr.valid? end when Hash args.each do |index, attrs| attr = Attribute.new(@context, attrs[:name]) self.attributes << attr if attr.valid? end else raise ArgumentError, "Invalid argument (#{args.class}) supplied to attributes=" end end
def build(params)
def build(params) params.with_indifferent_access.each do |key, value| if key.match(/^(a|v|p|m)$/) self.send("#{key}=", value) end end self end
def build_attribute(name = nil)
def build_attribute(name = nil) Attribute.new(@context, name).tap do |attribute| self.attributes << attribute end end
def build_value(val = nil)
def build_value(val = nil) Value.new(@context, val).tap do |value| self.values << value end end
def casted_values_for_attribute(attr)
def casted_values_for_attribute(attr) validated_values.map {|v| v.cast_to_type(predicate.type || attr.type)} end
def combinator
def combinator @attributes.size > 1 ? @combinator : nil end
def combinator=(val)
def combinator=(val) @combinator = ['and', 'or'].detect {|v| v == val.to_s} || nil end
def eql?(other)
def eql?(other) self.class == other.class && self.attributes == other.attributes && self.predicate == other.predicate && self.values == other.values && self.combinator == other.combinator end
def extract(context, key, values)
def extract(context, key, values) attributes, predicate = extract_attributes_and_predicate(key) if attributes.size > 0 combinator = key.match(/_(or|and)_/) ? $1 : nil condition = self.new(context) condition.build( :a => attributes, :p => predicate.name, :m => combinator, :v => [values] ) predicate.validate(condition.values) ? condition : nil end end
def extract_attributes_and_predicate(key)
def extract_attributes_and_predicate(key) str = key.dup name = Ransack.predicate_keys.detect {|p| str.sub!(/_#{p}$/, '')} predicate = Predicate.named(name) raise ArgumentError, "No valid predicate for #{key}" unless predicate attributes = str.split(/_and_|_or_/) [attributes, predicate] end
def first_attribute
def first_attribute attributes.first end
def formatted_values_for_attribute(attr)
def formatted_values_for_attribute(attr) casted_values_for_attribute(attr).map do |val| val = attr.ransacker.formatter.call(val) if attr.ransacker && attr.ransacker.formatter val = predicate.formatter.call(val) if predicate.formatter val end end
def hash
def hash [attributes, predicate, values, combinator].hash end
def key
def key @key ||= attributes.map(&:name).join("_#{combinator}_") + "_#{predicate.name}" end
def persisted?
def persisted? false end
def predicate=(predicate)
def predicate=(predicate) @predicate = predicate predicate end
def predicate_name
def predicate_name predicate.name if predicate end
def predicate_name=(name)
def predicate_name=(name) self.predicate = Predicate.named(name) end
def valid?
def valid? attributes.detect(&:valid?) && predicate && valid_arity? && predicate.validate(values) && valid_combinator? end
def valid_arity?
def valid_arity? values.size <= 1 || predicate.compound || %w(in not_in).include?(predicate.name) end
def valid_combinator?
def valid_combinator? attributes.size < 2 || ['and', 'or'].include?(combinator) end
def validated_values
def validated_values values.select {|v| predicate.validator ? predicate.validator.call(v.value) : v.present?} end
def value
def value predicate.compound ? values.map {|v| cast_value(v)} : cast_value(values.first) end
def values
def values @values ||= [] end
def values=(args)
def values=(args) case args when Array args.each do |val| val = Value.new(@context, val) self.values << val end when Hash args.each do |index, attrs| val = Value.new(@context, attrs[:value]) self.values << val end else raise ArgumentError, "Invalid argument (#{args.class}) supplied to values=" end end