class Sqreen::BindingAccessor
the value located at the given binding
Constants
- CLASS_VAR_KIND
- CONSTANT_KIND
- GLOBAL_VAR_KIND
- INDEX_KIND
- INSTANCE_VAR_KIND
- INTEGER_KIND
- KNOWN_TRANSFORMS
- LOCAL_VAR_KIND
- METHOD_KIND
- NIL_KIND
- PathElem
- RUBY_IDENTIFIER_CHAR
- SQREEN_VAR_KIND
- STRING_KIND
- SYMBOL_KIND
- TRANSFORM_ARGS_REGEXP
Attributes
expression[R]
final_transform[R]
path[R]
transform_args[R]
Public Class Methods
new(expression, convert = false)
click to toggle source
Expression to be accessed @param expression [String] expression to read @param convert [Boolean] wheter to convert objects to
simpler types (Array, Hash, String...)
# File lib/sqreen/binding_accessor.rb, line 21 def initialize(expression, convert = false) @transform_args = [] @final_transform = nil @expression = expression @path = [] @convert = convert parse(expression) end
Public Instance Methods
access(binding, framework = nil, instance = nil, arguments = nil, cbdata = nil, last_return = nil)
click to toggle source
Access data from the expression
# File lib/sqreen/binding_accessor.rb, line 31 def access(binding, framework = nil, instance = nil, arguments = nil, cbdata = nil, last_return = nil) env = [framework, instance, arguments, cbdata, last_return] value = nil @path.each do |component| value = resolve_component(value, component, binding, env) end value end
eql?(other)
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 53 def eql?(other) self.class == other.class && expression == other.expression && @convert == other.instance_variable_get('@convert') end
Also aliased as: ==
hash()
click to toggle source
implement eql? and hash for uniq
# File lib/sqreen/binding_accessor.rb, line 49 def hash expression.hash ^ @convert.hash end
resolve(*args)
click to toggle source
access and transform expression for the given binding
# File lib/sqreen/binding_accessor.rb, line 41 def resolve(*args) value = access(*args) value = transform(value) if @final_transform return convert(value) if @convert value end
Protected Instance Methods
convert(value)
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 250 def convert(value) case value when ::Exception { 'message' => value.message, 'backtrace' => value.backtrace } else value end end
error_state(msg)
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 246 def error_state(msg) "#{msg} at #{@scan.pos} after #{@scan.string[0...@scan.pos]} (#{@scan.string})" end
extract_transform(expression)
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 155 def extract_transform(expression) parts = expression.split('|') self.final_transform = parts.pop if parts.size > 1 parts.join('|').rstrip end
final_transform=(transform)
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 162 def final_transform=(transform) transform.strip! transform.sub!(TRANSFORM_ARGS_REGEXP, '') @transform_args = if Regexp.last_match Regexp.last_match(1).split(/,\s*/) else [] end unless KNOWN_TRANSFORMS.include?(transform) raise Sqreen::Exception, "Invalid transform #{transform}" end @final_transform = transform end
get_local(name, bind)
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 77 def get_local(name, bind) bind.local_variable_get(name) end
parse(expression)
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 132 def parse(expression) expression = extract_transform(expression) @scan = StringScanner.new(expression) until @scan.eos? pos = @scan.pos scalar = scan_scalar if scalar @path.push scalar return end if @path.empty? scan_push_variable else scan_push_method end scan_push_indexes scan_push_more_constant if @scan.scan(/\./).nil? raise Sqreen::Exception, error_state('Scan stuck') if @scan.pos == pos end ensure @scan = nil end
resolve_component(current_value, component, binding, env)
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 86 def resolve_component(current_value, component, binding, env) case component[:kind] when STRING_KIND, SYMBOL_KIND, INTEGER_KIND component[:value] when LOCAL_VAR_KIND get_local(component[:value], binding) when INSTANCE_VAR_KIND current_value.instance_variable_get("@#{component[:value]}") when CLASS_VAR_KIND current_value.class.class_variable_get("@@#{component[:value]}") when GLOBAL_VAR_KIND instance_eval("$#{component[:value]}") when CONSTANT_KIND if current_value current_value.const_get(component[:value].to_s) else Object.const_get(component[:value].to_s) end when METHOD_KIND current_value.send(component[:value]) when INDEX_KIND current_value[component[:value]] when NIL_KIND current_value when SQREEN_VAR_KIND resolve_sqreen_variable(component[:value], *env) else raise "Do not know how to handle this component #{component.inspect}" end end
resolve_sqreen_variable(what, framework, instance, args, cbdata, rv)
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 117 def resolve_sqreen_variable(what, framework, instance, args, cbdata, rv) case what when 'data' cbdata when 'rv' rv when 'args' args when 'inst' instance else framework.send(what) end end
scan_push_constant()
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 196 def scan_push_constant return unless @scan.scan(/([A-Z]#{RUBY_IDENTIFIER_CHAR}+)/) @path << PathElem.new(CONSTANT_KIND, @scan[1]) end
scan_push_indexes()
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 235 def scan_push_indexes while @scan.scan(/\[/) scalar = scan_scalar raise Sqreen::Exception, error_state('Invalid index') unless scalar unless @scan.scan(/\]/) raise Sqreen::Exception, error_state('Unfinished index') end @path << PathElem.new(INDEX_KIND, scalar[:value]) end end
scan_push_method()
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 225 def scan_push_method if @scan.scan(/@@(#{RUBY_IDENTIFIER_CHAR}+)/) @path << PathElem.new(CLASS_VAR_KIND, @scan[1]) elsif @scan.scan(/@(#{RUBY_IDENTIFIER_CHAR}+)/) @path << PathElem.new(INSTANCE_VAR_KIND, @scan[1]) elsif @scan.scan(/(#{RUBY_IDENTIFIER_CHAR}+)/) @path << PathElem.new(METHOD_KIND, @scan[1]) end end
scan_push_more_constant()
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 201 def scan_push_more_constant while @scan.scan(/::/) unless scan_push_constant raise Sqreen::Exception, error_state('No more constant') end end end
scan_push_variable()
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 209 def scan_push_variable if @scan.scan(/\$(#{RUBY_IDENTIFIER_CHAR}+)/) @path << PathElem.new(GLOBAL_VAR_KIND, @scan[1]) elsif @scan.scan(/@@(#{RUBY_IDENTIFIER_CHAR}+)/) @path << PathElem.new(CLASS_VAR_KIND, @scan[1]) elsif @scan.scan(/@(#{RUBY_IDENTIFIER_CHAR}+)/) @path << PathElem.new(INSTANCE_VAR_KIND, @scan[1]) elsif @scan.scan(/#\.(\w+)/) @path << PathElem.new(SQREEN_VAR_KIND, @scan[1]) elsif scan_push_constant nil elsif @scan.scan(/(#{RUBY_IDENTIFIER_CHAR}+)/u) @path << PathElem.new(LOCAL_VAR_KIND, @scan[1]) end end
scan_scalar()
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 178 def scan_scalar if @scan.scan(/\d+/) PathElem.new(INTEGER_KIND, @scan[0].to_i) elsif @scan.scan(/:(\w+)/) PathElem.new(SYMBOL_KIND, @scan[1].to_sym) elsif @scan.scan(/'((?:\\.|[^\\'])*)'/) PathElem.new(STRING_KIND, @scan[1]) elsif @scan.scan(/nil/) PathElem.new(NIL_KIND, nil) end end
transform(value)
click to toggle source
# File lib/sqreen/binding_accessor.rb, line 262 def transform(value) send(@final_transform, value, *@transform_args) if @final_transform end