Class: Squeel::Visitors::Base
- Inherits:
-
Object
- Object
- Squeel::Visitors::Base
- Defined in:
- lib/squeel/visitors/base.rb
Overview
The Base visitor class, containing the default behavior common to subclasses.
Direct Known Subclasses
Constant Summary collapse
- DISPATCH =
A hash that caches the method name to use for a visitor for a given class
Hash.new do |hash, klass| hash[klass] = "visit_#{(klass.name || '').gsub('::', '_')}" end
Instance Attribute Summary collapse
-
#context ⇒ Object
Returns the value of attribute context.
Class Method Summary collapse
-
.can_accept?(object) ⇒ Boolean
Whether or not visitors of this class can accept the given object.
Instance Method Summary collapse
-
#accept(object, parent = context.base) ⇒ Object
Accept an object.
-
#can_accept?(object) ⇒ Boolean
Whether or not the visitor can accept the given object.
-
#initialize(context = nil) ⇒ Base
constructor
Create a new Visitor that uses the supplied context object to contextualize visited nodes.
-
#quote(value) ⇒ Arel::Nodes::SqlLiteral
private
Quote a value based on its type, not on the last column used by the ARel visitor.
-
#quoted?(object) ⇒ Boolean
private
Important to avoid accidentally allowing the default ARel visitor’s last_column quoting behavior (where a value is quoted as though it is of the type of the last visited column).
-
#visit(object, parent) ⇒ Object
private
Visit the object.
Constructor Details
#initialize(context = nil) ⇒ Base
Create a new Visitor that uses the supplied context object to contextualize visited nodes.
15 16 17 |
# File 'lib/squeel/visitors/base.rb', line 15 def initialize(context = nil) @context = context end |
Instance Attribute Details
#context ⇒ Object
Returns the value of attribute context.
8 9 10 |
# File 'lib/squeel/visitors/base.rb', line 8 def context @context end |
Class Method Details
.can_accept?(object) ⇒ Boolean
Returns Whether or not visitors of this class can accept the given object.
37 38 39 40 41 42 43 44 |
# File 'lib/squeel/visitors/base.rb', line 37 def self.can_accept?(object) @can_accept ||= Hash.new do |hash, klass| hash[klass] = klass.ancestors.detect { |ancestor| private_method_defined? DISPATCH[ancestor] } ? true : false end @can_accept[object.class] end |
Instance Method Details
#accept(object, parent = context.base) ⇒ Object
Accept an object.
25 26 27 |
# File 'lib/squeel/visitors/base.rb', line 25 def accept(object, parent = context.base) visit(object, parent) end |
#can_accept?(object) ⇒ Boolean
Returns Whether or not the visitor can accept the given object.
31 32 33 |
# File 'lib/squeel/visitors/base.rb', line 31 def can_accept?(object) self.class.can_accept? object end |
#quote(value) ⇒ Arel::Nodes::SqlLiteral (private)
Quote a value based on its type, not on the last column used by the ARel visitor. This is occasionally necessary to avoid having ARel quote a value according to an integer column, converting ‘My String’ to 0.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/squeel/visitors/base.rb', line 77 def quote(value) if quoted? value case value when Array value.map {|v| quote(v)} when Range Range.new(quote(value.begin), quote(value.end), value.exclude_end?) else Arel.sql(arel_visitor.accept value) end else value end end |
#quoted?(object) ⇒ Boolean (private)
Important to avoid accidentally allowing the default ARel visitor’s last_column quoting behavior (where a value is quoted as though it is of the type of the last visited column). This can wreak havoc with Functions and Operations.
61 62 63 64 65 66 67 68 |
# File 'lib/squeel/visitors/base.rb', line 61 def quoted?(object) case object when Arel::Nodes::SqlLiteral, Bignum, Fixnum, Arel::SelectManager false else true end end |
#visit(object, parent) ⇒ Object (private)
Visit the object. This is not called directly, but instead via the public #accept method.
97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/squeel/visitors/base.rb', line 97 def visit(object, parent) send(DISPATCH[object.class], object, parent) rescue NoMethodError => e raise e if respond_to?(DISPATCH[object.class], true) superklass = object.class.ancestors.find { |klass| respond_to?(DISPATCH[klass], true) } raise(TypeError, "Cannot visit #{object.class}") unless superklass DISPATCH[object.class] = DISPATCH[superklass] retry end |