class Ransack::Nodes::Condition

Attributes

predicate[RW]

Public Class Methods

extract(context, key, values) click to toggle source
# File lib/ransack/nodes/condition.rb, line 11
def extract(context, key, values)
  attributes, predicate = extract_attributes_and_predicate(key, context)
  if attributes.size > 0 && predicate
    combinator = key.match(/_(or|and)_/) ? $1 : nil
    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

extract_attributes_and_predicate(key, context = nil) click to toggle source
# File lib/ransack/nodes/condition.rb, line 34
def extract_attributes_and_predicate(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 ArgumentError, "No valid predicate for #{key}"
  end
  if context.present? && context.attribute_method?(str)
    attributes = [str]
  else
    attributes = str.split(/_and_|_or_/)
  end
  [attributes, predicate]
end

Public Instance Methods

==(other)
Alias for: eql?
a()
Alias for: attributes
a=(args)
Alias for: attributes=
arel_predicate() click to toggle source
# File lib/ransack/adapters/active_record/ransack/nodes/condition.rb, line 5
def arel_predicate
  arel_predicate_for(attributes_array)
end
arel_predicate_for_attribute(attr) click to toggle source
# File lib/ransack/nodes/condition.rb, line 202
def arel_predicate_for_attribute(attr)
  if predicate.arel_predicate === Proc
    values = casted_values_for_attribute(attr)
    predicate.arel_predicate.call(
      predicate.wants_array ? values : values.first
      )
  else
    predicate.arel_predicate
  end
end
attributes() click to toggle source
# File lib/ransack/nodes/condition.rb, line 59
def attributes
  @attributes ||= []
end
Also aliased as: a
attributes=(args) click to toggle source
# File lib/ransack/nodes/condition.rb, line 64
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], attrs[:ransacker_args])
      self.attributes << attr if attr.valid?
    end
  else
    raise ArgumentError,
      "Invalid argument (#{args.class}) supplied to attributes="
  end
end
Also aliased as: a=
build(params) click to toggle source
# File lib/ransack/nodes/condition.rb, line 137
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
build_attribute(name = nil) click to toggle source
# File lib/ransack/nodes/condition.rb, line 117
def build_attribute(name = nil)
  Attribute.new(@context, name).tap do |attribute|
    self.attributes << attribute
  end
end
build_value(val = nil) click to toggle source
# File lib/ransack/nodes/condition.rb, line 123
def build_value(val = nil)
  Value.new(@context, val).tap do |value|
    self.values << value
  end
end
casted_values_for_attribute(attr) click to toggle source
# File lib/ransack/nodes/condition.rb, line 187
def casted_values_for_attribute(attr)
  validated_values.map { |v| v.cast(predicate.type || attr.type) }
end
combinator() click to toggle source
# File lib/ransack/nodes/condition.rb, line 107
def combinator
  @attributes.size > 1 ? @combinator : nil
end
Also aliased as: m
combinator=(val) click to toggle source
# File lib/ransack/nodes/condition.rb, line 111
def combinator=(val)
  @combinator = Constants::AND_OR.detect { |v| v == val.to_s } || nil
end
Also aliased as: m=
default_type() click to toggle source
# File lib/ransack/nodes/condition.rb, line 214
def default_type
  predicate.type || (attributes.first && attributes.first.type)
end
eql?(other) click to toggle source
# File lib/ransack/nodes/condition.rb, line 156
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: ==
formatted_values_for_attribute(attr) click to toggle source
# File lib/ransack/nodes/condition.rb, line 191
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
  predicate.wants_array ? formatted : formatted.first
end
hash() click to toggle source
# File lib/ransack/nodes/condition.rb, line 165
def hash
  [attributes, predicate, values, combinator].hash
end
inspect() click to toggle source
# File lib/ransack/nodes/condition.rb, line 218
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(Constants::COMMA_SPACE)
  "Condition <#{data}>"
end
key() click to toggle source
# File lib/ransack/nodes/condition.rb, line 151
def key
  @key ||= attributes.map(&:name).join("_#{combinator}_") +
    "_#{predicate.name}"
end
m()
Alias for: combinator
m=(val)
Alias for: combinator=
p()
Alias for: predicate_name
p=(name)
Alias for: predicate_name=
persisted?() click to toggle source
# File lib/ransack/nodes/condition.rb, line 147
def persisted?
  false
end
predicate_name() click to toggle source
# File lib/ransack/nodes/condition.rb, line 174
def predicate_name
  predicate.name if predicate
end
Also aliased as: p
predicate_name=(name) click to toggle source
# File lib/ransack/nodes/condition.rb, line 169
def predicate_name=(name)
  self.predicate = Predicate.named(name)
end
Also aliased as: p=
v()
Alias for: values
v=(args)
Alias for: values=
valid?() click to toggle source
# File lib/ransack/nodes/condition.rb, line 50
def valid?
  attributes.detect(&:valid?) && predicate && valid_arity? &&
    predicate.validate(values, default_type) && valid_combinator?
end
valid_arity?() click to toggle source
# File lib/ransack/nodes/condition.rb, line 55
def valid_arity?
  values.size <= 1 || predicate.wants_array
end
validated_values() click to toggle source
# File lib/ransack/nodes/condition.rb, line 183
def validated_values
  values.select { |v| predicate.validator.call(v.value) }
end
value() click to toggle source
# File lib/ransack/nodes/condition.rb, line 129
def value
  if predicate.wants_array
    values.map { |v| v.cast(default_type) }
  else
    values.first.cast(default_type)
  end
end
values() click to toggle source
# File lib/ransack/nodes/condition.rb, line 83
def values
  @values ||= []
end
Also aliased as: v
values=(args) click to toggle source
# File lib/ransack/nodes/condition.rb, line 88
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

arel_predicate_for(predicates) click to toggle source
# File lib/ransack/adapters/active_record/ransack/nodes/condition.rb, line 19
def arel_predicate_for(predicates)
  if predicates.size > 1
    combinator_for(predicates)
  else
    format_predicate(predicates.first)
  end
end
attributes_array() click to toggle source
# File lib/ransack/adapters/active_record/ransack/nodes/condition.rb, line 11
def attributes_array
  attributes.map do |a|
    a.attr.send(
      arel_predicate_for_attribute(a), formatted_values_for_attribute(a)
    )
  end
end
casted_array_with_in_predicate?(predicate) click to toggle source
# File lib/ransack/adapters/active_record/ransack/nodes/condition.rb, line 43
def casted_array_with_in_predicate?(predicate)
  return unless defined?(Arel::Nodes::Casted)
  predicate.class == Arel::Nodes::In &&
  predicate.right[0].respond_to?(:val) &&
  predicate.right[0].val.is_a?(Array)
end
combinator_for(predicates) click to toggle source
# File lib/ransack/adapters/active_record/ransack/nodes/condition.rb, line 27
def combinator_for(predicates)
  if combinator === Constants::AND
    Arel::Nodes::Grouping.new(Arel::Nodes::And.new(predicates))
  elsif combinator === Constants::OR
    predicates.inject(&:or)
  end
end
format_predicate(predicate) click to toggle source
# File lib/ransack/adapters/active_record/ransack/nodes/condition.rb, line 35
def format_predicate(predicate)
  predicate.tap do
    if casted_array_with_in_predicate?(predicate)
      predicate.right[0] = format_values_for(predicate.right[0])
    end
  end
end
format_values_for(predicate) click to toggle source
# File lib/ransack/adapters/active_record/ransack/nodes/condition.rb, line 50
def format_values_for(predicate)
  predicate.val.map do |value|
    value.is_a?(String) ? Arel::Nodes.build_quoted(value) : value
  end
end
valid_combinator?() click to toggle source
# File lib/ransack/nodes/condition.rb, line 233
def valid_combinator?
  attributes.size < 2 || Constants::AND_OR.include?(combinator)
end