class Ransack::Nodes::Condition
Attributes
Public Class Methods
Source
# File lib/ransack/nodes/condition.rb, line 13 def extract(context, key, values) attributes, predicate, combinator = extract_values_for_condition(key, context) if attributes.size > 0 && predicate condition = self.new(context) condition.build( a: attributes, p: predicate.name, m: combinator, v: predicate.wants_array ? Array(values) : [values] ) # TODO: Figure out what to do with multiple types of attributes, # if anything. Tempted to go with "garbage in, garbage out" here. if predicate.validate(condition.values, condition.default_type) condition else nil end end end
Private Class Methods
Source
# File lib/ransack/nodes/condition.rb, line 37 def extract_values_for_condition(key, context = nil) str = key.dup name = Predicate.detect_and_strip_from_string!(str) predicate = Predicate.named(name) unless predicate || Ransack.options[:ignore_unknown_conditions] raise InvalidSearchError, "No valid predicate for #{key}" end if context.present? str = context.ransackable_alias(str) end combinator = if str.match(/_(or|and)_/) $1 else nil end if context.present? && context.attribute_method?(str) attributes = [str] else attributes = str.split(/_and_|_or_/) end [attributes, predicate, combinator] end
Public Instance Methods
Source
# File lib/ransack/nodes/condition.rb, line 220 def arel_predicate raise "not implemented" end
Source
# File lib/ransack/nodes/condition.rb, line 247 def arel_predicate_for_attribute(attr) if predicate.arel_predicate === Proc values = casted_values_for_attribute(attr) unless predicate.wants_array values = values.first end predicate.arel_predicate.call(values) else predicate.arel_predicate end end
Source
# File lib/ransack/nodes/condition.rb, line 259 def attr_value_for_attribute(attr) return attr.attr if ActiveRecord::Base.connection.adapter_name == "PostgreSQL" predicate.case_insensitive ? attr.attr.lower : attr.attr rescue attr.attr end
Source
# File lib/ransack/nodes/condition.rb, line 76 def attributes @attributes ||= [] end
Also aliased as: a
Source
# File lib/ransack/nodes/condition.rb, line 81 def attributes=(args) case args when Array args.each do |name| build_attribute(name) end when Hash args.each do |index, attrs| build_attribute(attrs[:name], attrs[:ransacker_args]) end else raise ArgumentError, "Invalid argument (#{args.class}) supplied to attributes=" end end
Also aliased as: a=
Source
# File lib/ransack/nodes/condition.rb, line 174 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
Source
# File lib/ransack/nodes/condition.rb, line 150 def build_attribute(name = nil, ransacker_args = []) Attribute.new(@context, name, ransacker_args).tap do |attribute| @context.bind(attribute, attribute.name) self.attributes << attribute if name.nil? || attribute.valid? if predicate && !negative? @context.lock_association(attribute.parent) end end end
build_attribute
¶ ↑
This method was originally called from Nodes::Grouping#new_condition only, without arguments, without #valid? checking, to build a new grouping condition. After refactoring in 235eae3, it is now called from 2 places: 1. Nodes::Condition#attributes=, with +name+ argument passed or +name+ and +ransacker_args+. Attributes are included only if #valid?. 2. Nodes::Grouping#new_condition without arguments. In this case, the #valid? conditional needs to be bypassed, otherwise nothing is built. The `name.nil?` conditional below currently does this. TODO: Add test coverage for this behavior and ensure that `name.nil?` isn't fixing issue #701 by introducing untested regressions.
Source
# File lib/ransack/nodes/condition.rb, line 160 def build_value(val = nil) Value.new(@context, val).tap do |value| self.values << value end end
Source
# File lib/ransack/nodes/condition.rb, line 228 def casted_values_for_attribute(attr) validated_values.map { |v| v.cast(predicate.type || attr.type) } end
Source
# File lib/ransack/nodes/condition.rb, line 122 def combinator @attributes.size > 1 ? @combinator : nil end
Also aliased as: m
Source
# File lib/ransack/nodes/condition.rb, line 126 def combinator=(val) @combinator = Constants::AND_OR.detect { |v| v == val.to_s } || nil end
Also aliased as: m=
Source
# File lib/ransack/nodes/condition.rb, line 267 def default_type predicate.type || (attributes.first && attributes.first.type) end
Source
# File lib/ransack/nodes/condition.rb, line 193 def eql?(other) self.class == other.class && self.attributes == other.attributes && self.predicate == other.predicate && self.values == other.values && self.combinator == other.combinator end
Also aliased as: ==
Source
# File lib/ransack/nodes/condition.rb, line 232 def formatted_values_for_attribute(attr) formatted = casted_values_for_attribute(attr).map do |val| if attr.ransacker && attr.ransacker.formatter val = attr.ransacker.formatter.call(val) end val = predicate.format(val) val end if predicate.wants_array formatted else formatted.first end end
Source
# File lib/ransack/nodes/condition.rb, line 202 def hash [attributes, predicate, values, combinator].hash end
Source
# File lib/ransack/nodes/condition.rb, line 271 def inspect data = [ ['attributes'.freeze, a.try(:map, &:name)], ['predicate'.freeze, p], [Constants::COMBINATOR, m], ['values'.freeze, v.try(:map, &:value)] ] .reject { |e| e[1].blank? } .map { |v| "#{v[0]}: #{v[1]}" } .join(', '.freeze) "Condition <#{data}>" end
Source
# File lib/ransack/nodes/condition.rb, line 188 def key @key ||= attributes.map(&:name).join("_#{combinator}_") + "_#{predicate.name}" end
Source
# File lib/ransack/nodes/condition.rb, line 284 def negative? predicate.negative? end
Source
# File lib/ransack/nodes/condition.rb, line 215 def predicate_name predicate.name if predicate end
Also aliased as: p
Source
# File lib/ransack/nodes/condition.rb, line 206 def predicate_name=(name) self.predicate = Predicate.named(name) unless negative? attributes.each { |a| context.lock_association(a.parent) } end @predicate end
Also aliased as: p=
Source
# File lib/ransack/nodes/condition.rb, line 67 def valid? attributes.detect(&:valid?) && predicate && valid_arity? && predicate.validate(values, default_type) && valid_combinator? end
Source
# File lib/ransack/nodes/condition.rb, line 72 def valid_arity? values.size <= 1 || predicate.wants_array end
Source
# File lib/ransack/nodes/condition.rb, line 224 def validated_values values.select { |v| predicate.validator.call(v.value) } end
Source
# File lib/ransack/nodes/condition.rb, line 166 def value if predicate.wants_array values.map { |v| v.cast(default_type) } else values.first.cast(default_type) end end
Source
# File lib/ransack/nodes/condition.rb, line 98 def values @values ||= [] end
Also aliased as: v
Source
# File lib/ransack/nodes/condition.rb, line 103 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
Also aliased as: v=
Private Instance Methods
Source
# File lib/ransack/nodes/condition.rb, line 343 def casted_array?(predicate) predicate.value.is_a?(Array) && predicate.is_a?(Arel::Nodes::Casted) end
Source
# File lib/ransack/nodes/condition.rb, line 320 def combinator_method combinator === Constants::OR ? :or : :and end
Source
# File lib/ransack/nodes/condition.rb, line 324 def format_predicate(attribute) arel_pred = arel_predicate_for_attribute(attribute) arel_values = formatted_values_for_attribute(attribute) predicate = attr_value_for_attribute(attribute).public_send(arel_pred, arel_values) if in_predicate?(predicate) predicate.right = predicate.right.map do |pr| casted_array?(pr) ? format_values_for(pr) : pr end end predicate end
Source
# File lib/ransack/nodes/condition.rb, line 347 def format_values_for(predicate) predicate.value.map do |val| val.is_a?(String) ? Arel::Nodes.build_quoted(val) : val end end
Source
# File lib/ransack/nodes/condition.rb, line 338 def in_predicate?(predicate) return unless defined?(Arel::Nodes::Casted) predicate.class == Arel::Nodes::In || predicate.class == Arel::Nodes::NotIn end
Source
# File lib/ransack/nodes/condition.rb, line 353 def replace_right_node?(predicate) return false unless predicate.is_a?(Arel::Nodes::Binary) arel_node = predicate.right return false unless arel_node.is_a?(Arel::Nodes::Casted) relation, name = arel_node.attribute.values attribute_type = relation.type_for_attribute(name).type attribute_type == :integer && arel_node.value.is_a?(Integer) end
Source
# File lib/ransack/nodes/condition.rb, line 364 def valid_combinator? attributes.size < 2 || Constants::AND_OR.include?(combinator) end