mirror of
https://github.com/activerecord-hackery/ransack.git
synced 2022-11-09 13:47:45 -05:00
207 lines
5 KiB
Ruby
207 lines
5 KiB
Ruby
|
module Ransack
|
||
|
module Nodes
|
||
|
class Grouping < Node
|
||
|
attr_reader :conditions
|
||
|
i18n_word :condition, :and, :or
|
||
|
i18n_alias :c => :condition, :n => :and, :o => :or
|
||
|
|
||
|
delegate :each, :to => :values
|
||
|
|
||
|
def persisted?
|
||
|
false
|
||
|
end
|
||
|
|
||
|
def translate(key, options = {})
|
||
|
super or Translate.attribute(key.to_s, options.merge(:context => context))
|
||
|
end
|
||
|
|
||
|
def conditions
|
||
|
@conditions ||= []
|
||
|
end
|
||
|
alias :c :conditions
|
||
|
|
||
|
def conditions=(conditions)
|
||
|
case conditions
|
||
|
when Array
|
||
|
conditions.each do |attrs|
|
||
|
condition = Condition.new(@context).build(attrs)
|
||
|
self.conditions << condition if condition.valid?
|
||
|
end
|
||
|
when Hash
|
||
|
conditions.each do |index, attrs|
|
||
|
condition = Condition.new(@context).build(attrs)
|
||
|
self.conditions << condition if condition.valid?
|
||
|
end
|
||
|
end
|
||
|
|
||
|
self.conditions.uniq!
|
||
|
end
|
||
|
alias :c= :conditions=
|
||
|
|
||
|
def [](key)
|
||
|
if condition = conditions.detect {|c| c.key == key.to_s}
|
||
|
condition
|
||
|
else
|
||
|
nil
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def []=(key, value)
|
||
|
conditions.reject! {|c| c.key == key.to_s}
|
||
|
self.conditions << value
|
||
|
end
|
||
|
|
||
|
def values
|
||
|
conditions + ors + ands
|
||
|
end
|
||
|
|
||
|
def respond_to?(method_id)
|
||
|
super or begin
|
||
|
method_name = method_id.to_s
|
||
|
writer = method_name.sub!(/\=$/, '')
|
||
|
attribute_method?(method_name) ? true : false
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def build_condition(opts = {})
|
||
|
new_condition(opts).tap do |condition|
|
||
|
self.conditions << condition
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def new_condition(opts = {})
|
||
|
attrs = opts[:attributes] || 1
|
||
|
vals = opts[:values] || 1
|
||
|
condition = Condition.new(@context)
|
||
|
condition.predicate = Predicate.named('eq')
|
||
|
attrs.times { condition.build_attribute }
|
||
|
vals.times { condition.build_value }
|
||
|
condition
|
||
|
end
|
||
|
|
||
|
def ands
|
||
|
@ands ||= []
|
||
|
end
|
||
|
alias :n :ands
|
||
|
|
||
|
def ands=(ands)
|
||
|
case ands
|
||
|
when Array
|
||
|
ands.each do |attrs|
|
||
|
and_object = And.new(@context).build(attrs)
|
||
|
self.ands << and_object if and_object.values.any?
|
||
|
end
|
||
|
when Hash
|
||
|
ands.each do |index, attrs|
|
||
|
and_object = And.new(@context).build(attrs)
|
||
|
self.ands << and_object if and_object.values.any?
|
||
|
end
|
||
|
else
|
||
|
raise ArgumentError, "Invalid argument (#{ands.class}) supplied to ands="
|
||
|
end
|
||
|
end
|
||
|
alias :n= :ands=
|
||
|
|
||
|
def ors
|
||
|
@ors ||= []
|
||
|
end
|
||
|
alias :o :ors
|
||
|
|
||
|
def ors=(ors)
|
||
|
case ors
|
||
|
when Array
|
||
|
ors.each do |attrs|
|
||
|
or_object = Or.new(@context).build(attrs)
|
||
|
self.ors << or_object if or_object.values.any?
|
||
|
end
|
||
|
when Hash
|
||
|
ors.each do |index, attrs|
|
||
|
or_object = Or.new(@context).build(attrs)
|
||
|
self.ors << or_object if or_object.values.any?
|
||
|
end
|
||
|
else
|
||
|
raise ArgumentError, "Invalid argument (#{ors.class}) supplied to ors="
|
||
|
end
|
||
|
end
|
||
|
alias :o= :ors=
|
||
|
|
||
|
def method_missing(method_id, *args)
|
||
|
method_name = method_id.to_s
|
||
|
writer = method_name.sub!(/\=$/, '')
|
||
|
if attribute_method?(method_name)
|
||
|
writer ? write_attribute(method_name, *args) : read_attribute(method_name)
|
||
|
else
|
||
|
super
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def attribute_method?(name)
|
||
|
name = strip_predicate_and_index(name)
|
||
|
case name
|
||
|
when /^(n|o|c|ands|ors|conditions)=?$/
|
||
|
true
|
||
|
else
|
||
|
name.split(/_and_|_or_/).select {|n| !@context.attribute_method?(n)}.empty?
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def build_and(params = {})
|
||
|
params ||= {}
|
||
|
new_and(params).tap do |new_and|
|
||
|
self.ands << new_and
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def new_and(params = {})
|
||
|
And.new(@context).build(params)
|
||
|
end
|
||
|
|
||
|
def build_or(params = {})
|
||
|
params ||= {}
|
||
|
new_or(params).tap do |new_or|
|
||
|
self.ors << new_or
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def new_or(params = {})
|
||
|
Or.new(@context).build(params)
|
||
|
end
|
||
|
|
||
|
def build(params)
|
||
|
params.with_indifferent_access.each do |key, value|
|
||
|
case key
|
||
|
when /^(n|o|c)$/
|
||
|
self.send("#{key}=", value)
|
||
|
else
|
||
|
write_attribute(key.to_s, value)
|
||
|
end
|
||
|
end
|
||
|
self
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def write_attribute(name, val)
|
||
|
# TODO: Methods
|
||
|
if condition = Condition.extract(@context, name, val)
|
||
|
self[name] = condition
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def read_attribute(name)
|
||
|
if self[name].respond_to?(:value)
|
||
|
self[name].value
|
||
|
else
|
||
|
self[name]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def strip_predicate_and_index(str)
|
||
|
string = str.split(/\(/).first
|
||
|
Ransack::Configuration.predicate_keys.detect {|p| string.sub!(/_#{p}$/, '')}
|
||
|
string
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|
||
|
end
|