1
0
Fork 0
mirror of https://github.com/rubyjs/therubyrhino synced 2023-03-27 23:21:34 -04:00

some oop into access impls

AccessBase as a base class for different implementations
change DefaultAccess and RubyAccess to use AccessBase (but keep backwards compatibility with the "module" way)
This commit is contained in:
kares 2012-04-20 20:24:43 +02:00
parent f292f13686
commit 721c8a4355
6 changed files with 115 additions and 73 deletions

View file

@ -143,7 +143,7 @@ that attempts to mirror only attributes as properties as close as possible:
If you happen to come up with your own access strategy, just set it directly :
Rhino::Ruby::Scriptable.access = FooApp::BarAccess
Rhino::Ruby::Scriptable.access = FooApp::BarAccess.instance
=== Safe by default

View file

@ -38,24 +38,27 @@ module Rhino
@@access = nil
def self.access=(access)
@@access = access.is_a?(Module) ? access : begin
if access # Scriptable.access = :attribute
name = access.to_s.chomp('_access')
name = name[0, 1].capitalize << name[1..-1]
name = :"#{name}Access"
if Ruby.const_defined?(name)
Ruby.const_get(name) # e.g. Rhino::Ruby::AttributeAccess
else
const_get(name) # e.g. Rhino::Ruby::Scriptable::FooAccess
end
else # nil, false
access
@@access = ( access.respond_to?(:get) && access.respond_to?(:put) ) ? access :
begin
access =
if access && ! access.is_a?(Class) # Scriptable.access = :attribute
name = access.to_s.chomp('_access')
name = name[0, 1].capitalize << name[1..-1]
name = :"#{name}Access"
if Ruby.const_defined?(name)
Ruby.const_get(name) # e.g. Rhino::Ruby::AttributeAccess
else
const_get(name) # e.g. Rhino::Ruby::Scriptable::FooAccess
end
else # nil, false, Class
access
end
access.is_a?(Class) ? access.new : access
end
end
end
def self.access
@@access ||= Ruby::DefaultAccess
@@access ||= Ruby::DefaultAccess.new
end
private

View file

@ -4,5 +4,59 @@ module Rhino
autoload :DefaultAccess, "rhino/ruby/default_access"
autoload :AttributeAccess, "rhino/ruby/attribute_access"
class AccessBase
def has(object, name, scope)
# try [](name) method :
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
return true unless object[name].nil?
end
yield
end
def get(object, name, scope)
# try [](name) method :
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
unless (value = object[name]).nil?
return Rhino.to_javascript(value, scope)
end
end
yield
end
def put(object, name, value)
# try []=(name, value) method :
if object.respond_to?(:'[]=') && object.method(:'[]=').arity == 2
return object[name] = Rhino.to_ruby(value)
end
yield
end
end
module DeprecatedAccess
def has(object, name, scope, &block)
Rhino.warn "[DEPRECATION] `#{self.name}.has` is deprecated, please sub-class #{self.name} instead."
instance.has(object, name, scope, &block)
end
def get(object, name, scope, &block)
Rhino.warn "[DEPRECATION] `#{self.name}.get` is deprecated, please sub-class #{self.name} instead."
instance.get(object, name, scope, &block)
end
def put(object, name, value, &block)
Rhino.warn "[DEPRECATION] `#{self.name}.put` is deprecated, please sub-class #{self.name} instead."
instance.put(object, name, value, &block)
end
private
def instance
@instance ||= self.new
end
end
end
end

View file

@ -1,57 +1,41 @@
module Rhino
module Ruby
module AttributeAccess
class AttributeAccess < AccessBase
def self.has(object, name, scope)
def has(object, name, scope)
if object.respond_to?(name.to_s) ||
object.respond_to?(:"#{name}=") # might have a writer but no reader
return true
end
# try [](name) method :
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
return true if object[name]
end
yield
super
end
def self.get(object, name, scope)
def get(object, name, scope)
name_sym = name.to_s.to_sym
if object.respond_to?(name_sym)
method = object.method(name_sym)
if method.arity == 0 && # check if it is an attr_reader
( object.respond_to?(:"#{name}=") ||
object.instance_variables.find { |var| var.to_sym == :"@#{name}" } )
begin
return Rhino.to_javascript(method.call, scope)
rescue => e
raise Rhino::Ruby.wrap_error(e)
end
return Rhino.to_javascript(method.call, scope)
else
return Function.wrap(method.unbind)
end
elsif object.respond_to?(:"#{name}=")
return nil # it does have the property but is non readable
end
# try [](name) method :
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
if value = object[name]
return Rhino.to_javascript(value, scope)
end
end
yield
super
end
def self.put(object, name, value)
def put(object, name, value)
if object.respond_to?(set_name = :"#{name}=")
return object.send(set_name, Rhino.to_ruby(value))
end
# try []=(name, value) method :
if object.respond_to?(:'[]=') && object.method(:'[]=').arity == 2
return object[name] = Rhino.to_ruby(value)
end
yield
super
end
extend DeprecatedAccess # backward compatibility for a while
end
end
end

View file

@ -1,54 +1,38 @@
module Rhino
module Ruby
module DefaultAccess
class DefaultAccess < AccessBase
def self.has(object, name, scope)
def has(object, name, scope)
if object.respond_to?(name.to_s) ||
object.respond_to?("#{name}=")
return true
end
# try [](name) method :
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
return true if object[name]
end
yield
super
end
def self.get(object, name, scope)
def get(object, name, scope)
if object.respond_to?(name_s = name.to_s)
method = object.method(name_s)
if method.arity == 0
begin
return Rhino.to_javascript(method.call, scope)
rescue => e
raise Rhino::Ruby.wrap_error(e)
end
return Rhino.to_javascript(method.call, scope)
else
return Function.wrap(method.unbind)
end
elsif object.respond_to?("#{name}=")
return nil
end
# try [](name) method :
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
if value = object[name]
return Rhino.to_javascript(value, scope)
end
end
yield
super
end
def self.put(object, name, value)
def put(object, name, value)
if object.respond_to?(set_name = "#{name}=")
return object.send(set_name, Rhino.to_ruby(value))
end
# try []=(name, value) method :
if object.respond_to?(:'[]=') && object.method(:'[]=').arity == 2
return object[name] = Rhino.to_ruby(value)
end
yield
super
end
extend DeprecatedAccess # backward compatibility for a while
end
end
end

View file

@ -3,7 +3,7 @@ require File.expand_path('../spec_helper', File.dirname(__FILE__))
describe Rhino::Ruby::AttributeAccess do
before(:all) do
Rhino::Ruby::Scriptable.access = Rhino::Ruby::AttributeAccess
Rhino::Ruby::Scriptable.access = Rhino::Ruby::AttributeAccess.new
end
after(:all) do
@ -68,8 +68,8 @@ describe Rhino::Ruby::AttributeAccess do
it "might set access as a symbol" do
prev_access = Rhino::Ruby::Scriptable.access
attr_access = Rhino::Ruby::AttributeAccess
module FooAccess; end
module FooAccess; end # backward compatibility
class Foo2Access; end
begin
@ -77,19 +77,24 @@ describe Rhino::Ruby::AttributeAccess do
lambda {
Rhino::Ruby::Scriptable.access = :attribute
}.should_not raise_error
Rhino::Ruby::Scriptable.access.should == attr_access
Rhino::Ruby::Scriptable.access.should be_a Rhino::Ruby::AttributeAccess
Rhino::Ruby::Scriptable.access = nil
lambda {
Rhino::Ruby::Scriptable.access = :attribute_access
}.should_not raise_error
Rhino::Ruby::Scriptable.access.should == attr_access
Rhino::Ruby::Scriptable.access.should be_a Rhino::Ruby::AttributeAccess
lambda {
Rhino::Ruby::Scriptable.access = :foo
}.should_not raise_error
Rhino::Ruby::Scriptable.access.should == FooAccess
lambda {
Rhino::Ruby::Scriptable.access = :foo2
}.should_not raise_error
Rhino::Ruby::Scriptable.access.should be_a Foo2Access
lambda {
Rhino::Ruby::Scriptable.access = :bar
}.should raise_error
@ -99,4 +104,16 @@ describe Rhino::Ruby::AttributeAccess do
end
end
it "is backward compatibile with the 'module' way" do
Rhino::Ruby::AttributeAccess.respond_to?(:has).should be true
Rhino::Ruby::AttributeAccess.respond_to?(:get).should be true
Rhino::Ruby::AttributeAccess.respond_to?(:put).should be true
Rhino::Ruby::Scriptable.access = Rhino::Ruby::AttributeAccess
rb_object = Rhino::Ruby::Object.wrap Meh.new
rb_object.get('theMethod0', nil).should be_a(Rhino::Ruby::Function)
rb_object.has('non-existent-method', nil).should be false
end
end