Class: Kasket::Visitor

Inherits:
Arel::Visitors::Visitor
  • Object
show all
Defined in:
lib/kasket/visitor.rb

Instance Method Summary collapse

Constructor Details

#initialize(model_class, binds) ⇒ Visitor

Returns a new instance of Visitor.



5
6
7
8
# File 'lib/kasket/visitor.rb', line 5

def initialize(model_class, binds)
  @model_class = model_class
  @binds       = binds.dup
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



130
131
132
133
# File 'lib/kasket/visitor.rb', line 130

def method_missing(name, *args, &block)
  return :unsupported if name.to_s.start_with?('visit_')
  super
end

Instance Method Details

#accept(node) ⇒ Object



10
11
12
13
# File 'lib/kasket/visitor.rb', line 10

def accept(node)
  self.last_column = nil
  super
end

#column_for(name) ⇒ Object



23
24
25
# File 'lib/kasket/visitor.rb', line 23

def column_for(name)
  @model_class.columns_hash[name.to_s]
end

#last_columnObject



19
20
21
# File 'lib/kasket/visitor.rb', line 19

def last_column
  Thread.current[:arel_visitors_to_sql_last_column]
end

#last_column=(col) ⇒ Object



15
16
17
# File 'lib/kasket/visitor.rb', line 15

def last_column=(col)
  Thread.current[:arel_visitors_to_sql_last_column] = col
end

#literal(node) ⇒ Object Also known as: visit_String, visit_Fixnum, visit_TrueClass, visit_FalseClass, visit_Arel_Nodes_SqlLiteral



101
102
103
104
105
106
107
108
# File 'lib/kasket/visitor.rb', line 101

def literal(node)
  if node == '?'
    column, value = @binds.shift
    value.to_s
  else
    node.to_s
  end
end

#quoted(node) ⇒ Object

TODO: We are actually not using this?



120
121
122
# File 'lib/kasket/visitor.rb', line 120

def quoted(node)
  @model_class.connection.quote(node, self.last_column)
end

#respond_to?(name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


135
136
137
# File 'lib/kasket/visitor.rb', line 135

def respond_to?(name, include_private = false)
  return super || name.to_s.start_with?('visit_')
end

#visit_Arel_Attributes_Attribute(node) ⇒ Object



96
97
98
99
# File 'lib/kasket/visitor.rb', line 96

def visit_Arel_Attributes_Attribute(node)
  self.last_column = column_for(node.name)
  node.name.to_sym
end

#visit_Arel_Nodes_And(node) ⇒ Object



77
78
79
80
81
82
# File 'lib/kasket/visitor.rb', line 77

def visit_Arel_Nodes_And(node)
  attributes = node.children.map { |child| visit(child) }
  return :unsupported if attributes.include?(:unsupported)
  attributes.sort! { |pair1, pair2| pair1[0].to_s <=> pair2[0].to_s }
  { :attributes => attributes }
end

#visit_Arel_Nodes_BindParam(x) ⇒ Object

only gets used on 1.8.7



111
112
113
# File 'lib/kasket/visitor.rb', line 111

def visit_Arel_Nodes_BindParam(x)
  @binds.shift[1]
end

#visit_Arel_Nodes_Equality(node) ⇒ Object



91
92
93
94
# File 'lib/kasket/visitor.rb', line 91

def visit_Arel_Nodes_Equality(node)
  right = node.right
  [visit(node.left), right ? visit(right) : nil]
end

#visit_Arel_Nodes_In(node) ⇒ Object



84
85
86
87
88
89
# File 'lib/kasket/visitor.rb', line 84

def visit_Arel_Nodes_In(node)
  left = visit(node.left)
  return :unsupported if left != :id

  [left, visit(node.right)]
end

#visit_Arel_Nodes_JoinSource(node) ⇒ Object



67
68
69
70
71
# File 'lib/kasket/visitor.rb', line 67

def visit_Arel_Nodes_JoinSource(node)
  return :unsupported if !node.left || node.right.any?
  return :unsupported if !node.left.is_a?(Arel::Table)
  visit(node.left)
end

#visit_Arel_Nodes_Limit(node) ⇒ Object



63
64
65
# File 'lib/kasket/visitor.rb', line 63

def visit_Arel_Nodes_Limit(node)
  {:limit => node.value.to_i}
end

#visit_Arel_Nodes_SelectCore(node) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/kasket/visitor.rb', line 45

def visit_Arel_Nodes_SelectCore(node)
  return :unsupported if node.groups.any?
  return :unsupported if node.having
  return :unsupported if !AR30 && node.set_quantifier
  return :unsupported if !AR30 && (!node.source || node.source.empty?)
  return :unsupported if node.projections.size != 1

  select = node.projections[0]
  select = select.name if select.respond_to?(:name)
  return :unsupported if select != '*'

  parts = [visit(node.source)]

  parts += node.wheres.map {|where| visit(where) }

  parts.include?(:unsupported) ? :unsupported : parts
end

#visit_Arel_Nodes_SelectStatement(node) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/kasket/visitor.rb', line 27

def visit_Arel_Nodes_SelectStatement(node)
  return :unsupported if !AR30 && node.with
  return :unsupported if node.offset
  return :unsupported if node.lock
  return :unsupported if node.orders.any?
  return :unsupported if node.cores.size != 1

  query = visit_Arel_Nodes_SelectCore(node.cores[0])
  return query if query == :unsupported

  query = query.inject({}) do |memo, item|
    memo.merge(item)
  end

  query.merge!(visit(node.limit)) if node.limit
  query
end

#visit_Arel_Table(node) ⇒ Object



73
74
75
# File 'lib/kasket/visitor.rb', line 73

def visit_Arel_Table(node)
  {:from => node.name}
end

#visit_Array(node) ⇒ Object



115
116
117
# File 'lib/kasket/visitor.rb', line 115

def visit_Array(node)
  node.map {|value| quoted(value) }
end