Class: MetaWhere::Visitors::Predicate

Inherits:
Visitor
  • Object
show all
Defined in:
lib/meta_where/visitors/predicate.rb

Instance Attribute Summary

Attributes inherited from Visitor

#join_dependency, #tables

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Visitor

#accept, #can_accept?, #get_table, #initialize

Constructor Details

This class inherits a constructor from MetaWhere::Visitors::Visitor

Class Method Details

.visitablesObject



7
8
9
# File 'lib/meta_where/visitors/predicate.rb', line 7

def self.visitables
  [Hash, Array, MetaWhere::Or, MetaWhere::And, MetaWhere::Not, MetaWhere::Condition, MetaWhere::Function]
end

Instance Method Details

#visit_Array(o, parent) ⇒ Object



64
65
66
67
68
69
70
# File 'lib/meta_where/visitors/predicate.rb', line 64

def visit_Array(o, parent)
  if o.first.is_a? String
    join_dependency.join_base.send(:sanitize_sql, o)
  else
    o.map {|e| accept(e, parent)}.flatten
  end
end

#visit_Hash(o, parent) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/meta_where/visitors/predicate.rb', line 11

def visit_Hash(o, parent)
  parent ||= join_dependency.join_base
  parent = parent.name if parent.is_a? MetaWhere::JoinType
  table = tables[parent]
  predicates = o.map do |column, value|
    if value.is_a?(Hash)
      association = association_from_parent_and_column(parent, column)
      accept(value, association || column)
    elsif [MetaWhere::Condition, MetaWhere::And, MetaWhere::Or, MetaWhere::Not].include?(value.class)
      association = association_from_parent_and_column(parent, column)
      accept(value, association || column)
    elsif value.is_a?(Array) && !value.empty? && value.all? {|v| can_accept?(v)}
      association = association_from_parent_and_column(parent, column)
      value.map {|val| accept(val, association || column)}
    elsif (value.is_a?(ActiveRecord::Base) || array_of_activerecords(value)) &&
        reflection = parent.active_record.reflect_on_association(column.is_a?(MetaWhere::JoinType) ? column.name : column)
      accept_activerecord_values(column, value, parent, reflection)
    else
      if column.is_a?(MetaWhere::Column)
        method = column.method
        column = column.column
      else
        method = method_from_value(value)
      end

      if [String, Symbol].include?(column.class) && column.to_s.include?('.')
        table_name, column = column.to_s.split('.', 2)
        table = Arel::Table.new(table_name, :engine => parent.arel_engine)
      end

      unless valid_comparison_method?(method)
        raise ::ActiveRecord::StatementInvalid, "No comparison method named `#{method}` exists for column `#{column}`"
      end

      if attribute = attribute_from_column_and_table(column, table)
        attribute.send(method, args_for_predicate(value))
      else
        raise ::ActiveRecord::StatementInvalid, "No attribute named `#{column}` exists for table `#{table.name}`"
      end

    end
  end

  predicates.flatten!

  if predicates.size > 1
    first = predicates.shift
    Arel::Nodes::Grouping.new(predicates.inject(first) {|memo, expr| Arel::Nodes::And.new([memo, expr])})
  else
    predicates.first
  end
end

#visit_MetaWhere_And(o, parent) ⇒ Object



76
77
78
# File 'lib/meta_where/visitors/predicate.rb', line 76

def visit_MetaWhere_And(o, parent)
  accept(o.condition1, parent).and(accept(o.condition2, parent))
end

#visit_MetaWhere_Condition(o, parent) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/meta_where/visitors/predicate.rb', line 84

def visit_MetaWhere_Condition(o, parent)
  table = tables[parent]

  unless attribute = attribute_from_column_and_table(o.column, table)
    raise ::ActiveRecord::StatementInvalid, "No attribute named `#{o.column}` exists for table `#{table.name}`"
  end

  unless valid_comparison_method?(o.method)
    raise ::ActiveRecord::StatementInvalid, "No comparison method named `#{o.method}` exists for column `#{o.column}`"
  end
  attribute.send(o.method, args_for_predicate(o.value))
end

#visit_MetaWhere_Function(o, parent) ⇒ Object



97
98
99
100
101
# File 'lib/meta_where/visitors/predicate.rb', line 97

def visit_MetaWhere_Function(o, parent)
  self.table = tables[parent]

  o.to_sqlliteral
end

#visit_MetaWhere_Not(o, parent) ⇒ Object



80
81
82
# File 'lib/meta_where/visitors/predicate.rb', line 80

def visit_MetaWhere_Not(o, parent)
  accept(o.expr, parent).not
end

#visit_MetaWhere_Or(o, parent) ⇒ Object



72
73
74
# File 'lib/meta_where/visitors/predicate.rb', line 72

def visit_MetaWhere_Or(o, parent)
  accept(o.condition1, parent).or(accept(o.condition2, parent))
end