diff options
-rw-r--r-- | lib/arel/visitors/depth_first.rb | 4 | ||||
-rw-r--r-- | lib/arel/visitors/dot.rb | 1 | ||||
-rw-r--r-- | lib/arel/visitors/reduce.rb | 8 | ||||
-rw-r--r-- | lib/arel/visitors/to_sql.rb | 10 | ||||
-rw-r--r-- | lib/arel/visitors/visitor.rb | 31 | ||||
-rw-r--r-- | lib/arel/visitors/where_sql.rb | 2 | ||||
-rw-r--r-- | test/visitors/test_bind_visitor.rb | 6 | ||||
-rw-r--r-- | test/visitors/test_to_sql.rb | 2 |
8 files changed, 38 insertions, 26 deletions
diff --git a/lib/arel/visitors/depth_first.rb b/lib/arel/visitors/depth_first.rb index eab20ac831..a434f404c7 100644 --- a/lib/arel/visitors/depth_first.rb +++ b/lib/arel/visitors/depth_first.rb @@ -3,6 +3,7 @@ module Arel class DepthFirst < Arel::Visitors::Visitor def initialize block = nil @block = block || Proc.new + super() end private @@ -86,6 +87,7 @@ module Arel alias :visit_Arel_Nodes_RightOuterJoin :binary alias :visit_Arel_Nodes_TableAlias :binary alias :visit_Arel_Nodes_Values :binary + alias :visit_Arel_Nodes_Union :binary def visit_Arel_Nodes_StringJoin o visit o.left @@ -116,6 +118,8 @@ module Arel alias :visit_Arel_Nodes_SqlLiteral :terminal alias :visit_Arel_Nodes_BindParam :terminal alias :visit_Arel_Nodes_Window :terminal + alias :visit_Arel_Nodes_True :terminal + alias :visit_Arel_Nodes_False :terminal alias :visit_BigDecimal :terminal alias :visit_Bignum :terminal alias :visit_Class :terminal diff --git a/lib/arel/visitors/dot.rb b/lib/arel/visitors/dot.rb index 12cce1e266..e0c02d717a 100644 --- a/lib/arel/visitors/dot.rb +++ b/lib/arel/visitors/dot.rb @@ -15,6 +15,7 @@ module Arel end def initialize + super() @nodes = [] @edges = [] @node_stack = [] diff --git a/lib/arel/visitors/reduce.rb b/lib/arel/visitors/reduce.rb index 9670cad27c..1d74934fe5 100644 --- a/lib/arel/visitors/reduce.rb +++ b/lib/arel/visitors/reduce.rb @@ -10,14 +10,14 @@ module Arel private def visit object, collector - send dispatch[object.class], object, collector + send dispatch[object.class.name], object, collector rescue NoMethodError => e - raise e if respond_to?(dispatch[object.class], true) + raise e if respond_to?(dispatch[object.class.name], true) superklass = object.class.ancestors.find { |klass| - respond_to?(dispatch[klass], true) + respond_to?(dispatch[klass.name], true) } raise(TypeError, "Cannot visit #{object.class}") unless superklass - dispatch[object.class] = dispatch[superklass] + dispatch[object.class.name] = dispatch[superklass.name] retry end end diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index dea6830e8f..7bef8feded 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -59,8 +59,8 @@ module Arel DISTINCT = 'DISTINCT' # :nodoc: def initialize connection + super() @connection = connection - @schema_cache = connection.schema_cache end def compile node, &block @@ -69,6 +69,10 @@ module Arel private + def schema_cache + @connection.schema_cache + end + def visit_Arel_Nodes_DeleteStatement o, collector collector << "DELETE FROM " collector = visit o.relation, collector @@ -160,7 +164,7 @@ module Arel end def table_exists? name - @schema_cache.table_exists? name + schema_cache.table_exists? name end def column_for attr @@ -174,7 +178,7 @@ module Arel end def column_cache(table) - @schema_cache.columns_hash(table) + schema_cache.columns_hash(table) end def visit_Arel_Nodes_Values o, collector diff --git a/lib/arel/visitors/visitor.rb b/lib/arel/visitors/visitor.rb index 0730c15794..2317d0c95f 100644 --- a/lib/arel/visitors/visitor.rb +++ b/lib/arel/visitors/visitor.rb @@ -1,32 +1,39 @@ module Arel module Visitors class Visitor + def initialize + @dispatch = Hash.new do |hash, class_name| + raise if class_name == 'Arel::Nodes::Union' + hash[class_name] = "visit_#{(class_name || '').gsub('::', '_')}" + end + + # pre-populate cache. FIXME: this should be passed in to each + # instance, but we can do that later. + self.class.private_instance_methods.sort.each do |name| + next unless name =~ /^visit_(.*)$/ + @dispatch[$1.gsub('_', '::')] = name + end + end + def accept object visit object end private - DISPATCH = Hash.new do |hash, visitor_class| - hash[visitor_class] = - Hash.new do |method_hash, node_class| - method_hash[node_class] = "visit_#{(node_class.name || '').gsub('::', '_')}" - end - end - def dispatch - DISPATCH[self.class] + @dispatch end def visit object - send dispatch[object.class], object + send dispatch[object.class.name], object rescue NoMethodError => e - raise e if respond_to?(dispatch[object.class], true) + raise e if respond_to?(dispatch[object.class.name], true) superklass = object.class.ancestors.find { |klass| - respond_to?(dispatch[klass], true) + respond_to?(dispatch[klass.name], true) } raise(TypeError, "Cannot visit #{object.class}") unless superklass - dispatch[object.class] = dispatch[superklass] + dispatch[object.class.name] = dispatch[superklass.name] retry end end diff --git a/lib/arel/visitors/where_sql.rb b/lib/arel/visitors/where_sql.rb index 27dde73673..afde15a6c5 100644 --- a/lib/arel/visitors/where_sql.rb +++ b/lib/arel/visitors/where_sql.rb @@ -1,6 +1,8 @@ module Arel module Visitors class WhereSql < Arel::Visitors::ToSql + private + def visit_Arel_Nodes_SelectCore o, collector collector << "WHERE " inject_join o.wheres, collector, ' AND ' diff --git a/test/visitors/test_bind_visitor.rb b/test/visitors/test_bind_visitor.rb index 5171bbe57c..333636ed51 100644 --- a/test/visitors/test_bind_visitor.rb +++ b/test/visitors/test_bind_visitor.rb @@ -35,9 +35,6 @@ module Arel def test_visitor_yields_on_binds visitor = Class.new(Arel::Visitors::ToSql) { - def initialize omg - end - include Arel::Visitors::BindVisitor }.new nil @@ -49,9 +46,6 @@ module Arel def test_visitor_only_yields_on_binds visitor = Class.new(Arel::Visitors::ToSql) { - def initialize omg - end - include Arel::Visitors::BindVisitor }.new(nil) diff --git a/test/visitors/test_to_sql.rb b/test/visitors/test_to_sql.rb index b495c4d994..195566902b 100644 --- a/test/visitors/test_to_sql.rb +++ b/test/visitors/test_to_sql.rb @@ -29,7 +29,7 @@ module Arel end def dispatch - { Arel::Table => 'hello' } + { Arel::Table.name => 'hello' } end }.new |