seat-belt 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +29 -0
- data/.travis.yml +6 -0
- data/Changelog.md +55 -0
- data/Gemfile +15 -0
- data/Guardfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +705 -0
- data/Rakefile +1 -0
- data/ext/.gitkeep +0 -0
- data/lib/seatbelt.rb +37 -0
- data/lib/seatbelt/collections/collection.rb +56 -0
- data/lib/seatbelt/core.rb +15 -0
- data/lib/seatbelt/core/callee.rb +35 -0
- data/lib/seatbelt/core/eigenmethod.rb +150 -0
- data/lib/seatbelt/core/eigenmethod_proxy.rb +45 -0
- data/lib/seatbelt/core/ext/core_ext.rb +0 -0
- data/lib/seatbelt/core/gate.rb +198 -0
- data/lib/seatbelt/core/ghost_tunnel.rb +81 -0
- data/lib/seatbelt/core/implementation.rb +158 -0
- data/lib/seatbelt/core/interface.rb +51 -0
- data/lib/seatbelt/core/iterators/method_config.rb +50 -0
- data/lib/seatbelt/core/lookup_table.rb +101 -0
- data/lib/seatbelt/core/pool.rb +90 -0
- data/lib/seatbelt/core/property.rb +161 -0
- data/lib/seatbelt/core/proxy.rb +135 -0
- data/lib/seatbelt/core/synthesizeable.rb +50 -0
- data/lib/seatbelt/core/terminal.rb +59 -0
- data/lib/seatbelt/dependencies.rb +5 -0
- data/lib/seatbelt/document.rb +175 -0
- data/lib/seatbelt/errors.rb +1 -0
- data/lib/seatbelt/errors/errors.rb +150 -0
- data/lib/seatbelt/gate_config.rb +59 -0
- data/lib/seatbelt/ghost.rb +140 -0
- data/lib/seatbelt/models.rb +9 -0
- data/lib/seatbelt/seatbelt.rb +10 -0
- data/lib/seatbelt/synthesizer.rb +3 -0
- data/lib/seatbelt/synthesizers/document.rb +16 -0
- data/lib/seatbelt/synthesizers/mongoid.rb +16 -0
- data/lib/seatbelt/synthesizers/synthesizer.rb +146 -0
- data/lib/seatbelt/tape.rb +2 -0
- data/lib/seatbelt/tape_deck.rb +71 -0
- data/lib/seatbelt/tapes/tape.rb +105 -0
- data/lib/seatbelt/tapes/util/delegate.rb +56 -0
- data/lib/seatbelt/translator.rb +66 -0
- data/lib/seatbelt/version.rb +3 -0
- data/seatbelt.gemspec +27 -0
- data/spec/lib/seatbelt/core/eigenmethod_spec.rb +102 -0
- data/spec/lib/seatbelt/core/gate_spec.rb +521 -0
- data/spec/lib/seatbelt/core/ghost_tunnel_spec.rb +21 -0
- data/spec/lib/seatbelt/core/lookup_table_spec.rb +234 -0
- data/spec/lib/seatbelt/core/pool_spec.rb +270 -0
- data/spec/lib/seatbelt/core/proxy_spec.rb +108 -0
- data/spec/lib/seatbelt/core/terminal_spec.rb +184 -0
- data/spec/lib/seatbelt/document_spec.rb +287 -0
- data/spec/lib/seatbelt/gate_config_spec.rb +98 -0
- data/spec/lib/seatbelt/ghost_spec.rb +568 -0
- data/spec/lib/seatbelt/synthesizers/document_spec.rb +47 -0
- data/spec/lib/seatbelt/synthesizers/mongoid_spec.rb +134 -0
- data/spec/lib/seatbelt/synthesizers/synthesizer_spec.rb +112 -0
- data/spec/lib/seatbelt/tape_deck_spec.rb +180 -0
- data/spec/lib/seatbelt/tapes/tape_spec.rb +115 -0
- data/spec/lib/seatbelt/translator_spec.rb +108 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/implementations/seatbelt_environment.rb +19 -0
- data/spec/support/shared_examples/shared_api_class.rb +7 -0
- data/spec/support/shared_examples/shared_collection_child.rb +7 -0
- data/spec/support/worlds/eigenmethod_world.rb +7 -0
- metadata +205 -0
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/ext/.gitkeep
ADDED
File without changes
|
data/lib/seatbelt.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require "seatbelt/dependencies"
|
2
|
+
require "seatbelt/version"
|
3
|
+
require "seatbelt/seatbelt"
|
4
|
+
|
5
|
+
module Seatbelt
|
6
|
+
|
7
|
+
METHOD_EXCLUDE_DIRECTIVES = %w{ :: }
|
8
|
+
|
9
|
+
# Internal: Checks a directive if allowed. Raises a DirectiveNotAllowedError
|
10
|
+
# if directive is not allowed.
|
11
|
+
#
|
12
|
+
# directive - the directive String to check.
|
13
|
+
#
|
14
|
+
# Returns nothing
|
15
|
+
def self.check_directive(directive)
|
16
|
+
if directive.in?(METHOD_EXCLUDE_DIRECTIVES)
|
17
|
+
raise Seatbelt::Errors::DirectiveNotAllowedError
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# Public: Configures the Gate. Needs a block.
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
#
|
26
|
+
# Seatbelt.configure_gate do |config|
|
27
|
+
# config.method_directive_instance = "|"
|
28
|
+
# config.method_directive_class = "~"
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# Returns nothing.
|
32
|
+
def self.configure_gate
|
33
|
+
yield GateConfig if block_given?
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Seatbelt
|
2
|
+
module Collections
|
3
|
+
|
4
|
+
# Public: The datastructure used as primitive in
|
5
|
+
# Seatbelt::Collections::Collection
|
6
|
+
#
|
7
|
+
class Array < ::Array; end
|
8
|
+
|
9
|
+
# Public: The base collection attribute type that is used in 'has_many'
|
10
|
+
# associations.
|
11
|
+
#
|
12
|
+
# Needs a corrosponding model.
|
13
|
+
# See Seatbelt::Dcoument::Associations for further details.
|
14
|
+
class Collection < Array#Virtus::Attribute::Collection
|
15
|
+
|
16
|
+
# Public: Initializes the collections primitive to allow later type
|
17
|
+
# checking.Adds a method 'acceptable_item_name' to the primitive, that
|
18
|
+
# is later called at the time of type checking to match the allowed class.
|
19
|
+
#
|
20
|
+
# klass - The associatzed klass that is insertable into the collection.
|
21
|
+
#
|
22
|
+
def self.initialize_primitive(klass)
|
23
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
24
|
+
def acceptable_item_name
|
25
|
+
return "#{klass.name}"
|
26
|
+
end
|
27
|
+
RUBY
|
28
|
+
end
|
29
|
+
|
30
|
+
# Public: Adds an object to the 'has_many' association.
|
31
|
+
#
|
32
|
+
# item - An instance of the model class used within the collection
|
33
|
+
# or an Hash with attribute key/value pairs.
|
34
|
+
#
|
35
|
+
# Example
|
36
|
+
# region.hotels << {:name => "Radisson London Stansted"}
|
37
|
+
# region.hotels << super_hotel_in_dubai
|
38
|
+
#
|
39
|
+
# Raises Seatbelt::Errors::TypeMissmatchError if unexpected object
|
40
|
+
# is passed.
|
41
|
+
def <<(item)
|
42
|
+
case item.class.name
|
43
|
+
when acceptable_item_name then super(item)
|
44
|
+
when "Hash" then
|
45
|
+
begin
|
46
|
+
super(Module.const_get(acceptable_item_name).new(item))
|
47
|
+
end
|
48
|
+
else
|
49
|
+
raise Seatbelt::Errors::TypeMissmatchError.
|
50
|
+
new(acceptable_item_name,
|
51
|
+
item.class.name)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'seatbelt/core/lookup_table'
|
2
|
+
require 'seatbelt/core/pool'
|
3
|
+
require 'seatbelt/core/property'
|
4
|
+
require 'seatbelt/core/interface'
|
5
|
+
require 'seatbelt/core/ghost_tunnel'
|
6
|
+
require 'seatbelt/core/synthesizeable'
|
7
|
+
require 'seatbelt/core/implementation'
|
8
|
+
require 'seatbelt/core/gate'
|
9
|
+
require 'seatbelt/core/eigenmethod'
|
10
|
+
require 'seatbelt/core/eigenmethod_proxy'
|
11
|
+
require 'seatbelt/core/terminal'
|
12
|
+
require 'seatbelt/core/callee'
|
13
|
+
require 'seatbelt/core/proxy'
|
14
|
+
require 'seatbelt/core/ext/core_ext'
|
15
|
+
require 'seatbelt/core/iterators/method_config'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Seatbelt
|
2
|
+
|
3
|
+
# Public: Handles passing the call of API Methods to the Terminal.
|
4
|
+
module Callee
|
5
|
+
extend self
|
6
|
+
|
7
|
+
# Public: Handles the calling of a API method (instance and class scope).
|
8
|
+
#
|
9
|
+
# klass - The class or instance of the class containing the API method
|
10
|
+
# options - A options Hash to refine required values
|
11
|
+
# :lookup_tbl - The class lookup table instance.
|
12
|
+
# :scope - The scope the API method should be called on.
|
13
|
+
# :method_name - The API method's name
|
14
|
+
# *args - argument list of the API method
|
15
|
+
# &block - An optional block passed to the API method
|
16
|
+
#
|
17
|
+
# Returns the return value of the API methods implementation method if
|
18
|
+
# the method configuration was found at the lookup table.
|
19
|
+
def handle(klass, options, *args, &block)
|
20
|
+
lookup_tbl = options[:lookup_tbl]
|
21
|
+
scope = options[:scope]
|
22
|
+
method_name = options[:method_name]
|
23
|
+
|
24
|
+
api_method_config = lookup_tbl.
|
25
|
+
find_method(method_name, scope: scope)
|
26
|
+
arity = api_method_config[method_name][:arity]
|
27
|
+
if api_method_config[method_name][:block_required]
|
28
|
+
if block.nil?
|
29
|
+
raise Seatbelt::Errors::ApiMethodBlockRequiredError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
Seatbelt::Terminal.call(method_name, klass, arity, *args, &block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
module Seatbelt
|
2
|
+
|
3
|
+
# Public: A configuration class that contains the implementation method
|
4
|
+
# directives and attributes.
|
5
|
+
class Eigenmethod
|
6
|
+
|
7
|
+
attr_accessor :scope_level,
|
8
|
+
:namespace,
|
9
|
+
:implemented_as,
|
10
|
+
:method,
|
11
|
+
:method_implementation_type,
|
12
|
+
:arity,
|
13
|
+
:delegated
|
14
|
+
|
15
|
+
attr_writer :receiver
|
16
|
+
|
17
|
+
|
18
|
+
# Public: The receiver of the implementation method. This is always an
|
19
|
+
# instance whether it defines a class method or instance method
|
20
|
+
# implementation.
|
21
|
+
#
|
22
|
+
# Returns receivers instance.
|
23
|
+
def receiver
|
24
|
+
@receiver
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# Implementation type at remote class (API class) side.
|
29
|
+
#
|
30
|
+
# Returns true if an instance method is implemented, otherwise false.
|
31
|
+
def instance_level?
|
32
|
+
self.scope_level.eql?(:instance)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Implementation type at remote class (API class) side.
|
36
|
+
#
|
37
|
+
# Returns true if a class method is implemented, otherwise false.
|
38
|
+
def class_level?
|
39
|
+
not self.instance_level?
|
40
|
+
end
|
41
|
+
|
42
|
+
# Implementation type at the implementation class side.
|
43
|
+
#
|
44
|
+
# Returns true if a class method is implemented, otherwise false.
|
45
|
+
def class_method_implementation?
|
46
|
+
self.method_implementation_type.eql?(:class)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Implementation type at the implementation class side.
|
50
|
+
#
|
51
|
+
# Returns true if an instance method is implemented, otherwise false.
|
52
|
+
def instance_method_implementation?
|
53
|
+
not class_method_implementation?
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# Public: Calls the implementation method of an API method call.
|
58
|
+
#
|
59
|
+
# *args - argument list for the implementation method.
|
60
|
+
# &block - A block if needed.
|
61
|
+
#
|
62
|
+
# Returns the evaluated value.
|
63
|
+
def call(*args, &block)
|
64
|
+
return __send_class_level(*args, &block) if class_level?
|
65
|
+
return __send_instance_level(*args, &block) if instance_level?
|
66
|
+
end
|
67
|
+
|
68
|
+
def [](attr)
|
69
|
+
self.send(attr)
|
70
|
+
end
|
71
|
+
|
72
|
+
alias_method :has_key?, :respond_to?
|
73
|
+
alias_method :scope, :scope_level
|
74
|
+
alias_method :scope=, :scope_level=
|
75
|
+
|
76
|
+
|
77
|
+
# Creates the corrosponding class on the receiver and defines the proxy
|
78
|
+
# tunnel on the receivers proxy object.
|
79
|
+
#
|
80
|
+
# klass_object - The API Class or an instance of the API class.
|
81
|
+
#
|
82
|
+
def init_klass_on_receiver(klass_object)
|
83
|
+
if instance_level?
|
84
|
+
__generate_proxy_object(@callee, klass_object)
|
85
|
+
end
|
86
|
+
if class_level?
|
87
|
+
if class_method_implementation?
|
88
|
+
__generate_proxy_object(receiver, klass_object)
|
89
|
+
else
|
90
|
+
if method_implementation_type.eql?(:instance)
|
91
|
+
@callee = callee.new if @callee.respond_to?(:new)
|
92
|
+
@callee.instance_variable_set(:@proxy,Seatbelt::Proxy.new)
|
93
|
+
__generate_proxy_object(callee, klass_object)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Accessor of the api method implementation call object.
|
100
|
+
def callee
|
101
|
+
@callee
|
102
|
+
end
|
103
|
+
|
104
|
+
def __generate_proxy_object(receiver_, klass_object)
|
105
|
+
runner = lambda do |receiver_scope|
|
106
|
+
receiver_scope.send(:proxy_object).instance_variable_set(:@klass, klass_object)
|
107
|
+
receiver_scope.send(:proxy_object).class_eval code
|
108
|
+
receiver_scope.class.send(:define_method, :proxy) do
|
109
|
+
return self.proxy_object
|
110
|
+
end
|
111
|
+
#p receiver_scope.send(:proxy_object)
|
112
|
+
return receiver_scope
|
113
|
+
end
|
114
|
+
runner.call(receiver_)
|
115
|
+
end
|
116
|
+
|
117
|
+
def code
|
118
|
+
<<-RUBY
|
119
|
+
def klass
|
120
|
+
return instance_variable_get(:@klass)
|
121
|
+
end
|
122
|
+
private :klass
|
123
|
+
RUBY
|
124
|
+
end
|
125
|
+
|
126
|
+
def __send_class_level(*args, &block)
|
127
|
+
if class_method_implementation?
|
128
|
+
object = receiver
|
129
|
+
else
|
130
|
+
object = callee
|
131
|
+
end
|
132
|
+
object.send(@method, *args, &block)
|
133
|
+
end
|
134
|
+
|
135
|
+
def __send_instance_level(*args, &block)
|
136
|
+
if method.respond_to?(:bind)
|
137
|
+
value = method.bind(callee).call(*args, &block)
|
138
|
+
else
|
139
|
+
value = callee.send(method, *args, &block)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
private :__send_instance_level,
|
144
|
+
:__send_class_level,
|
145
|
+
:__generate_proxy_object,
|
146
|
+
:code,
|
147
|
+
:callee
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Seatbelt
|
2
|
+
module EigenmethodProxy
|
3
|
+
extend self
|
4
|
+
|
5
|
+
# Public: Creates or duplicates a new eigenmethod object. Creates the proxy
|
6
|
+
# object on the Eigenmethod and adds this eigenmethod object to
|
7
|
+
# Terminal#luggage or just returns the duplicated or thenewly created object
|
8
|
+
#
|
9
|
+
# *args - An argument list consisting of:
|
10
|
+
# proxy - A Seatbelt::Proxy instance
|
11
|
+
# options - An options hash
|
12
|
+
# :eigenmethod - the eigenmethod to duplicate
|
13
|
+
# :object - the object the eigenmethod should be bind to
|
14
|
+
# :receiver - An instance or class representation of the
|
15
|
+
# implementation class
|
16
|
+
# :add_to - Eigenmethod should added to Terminal#luggage
|
17
|
+
# (defaults to true)
|
18
|
+
# :return method - Eigenmethod should be returned
|
19
|
+
#
|
20
|
+
def set(*args)
|
21
|
+
options = args.extract_options!
|
22
|
+
proxy = args.pop
|
23
|
+
eigenmethod = options[:eigenmethod]
|
24
|
+
obj = options[:object]
|
25
|
+
receiver = options[:receiver]
|
26
|
+
index = Terminal.luggage.index(eigenmethod)
|
27
|
+
add_to_luggage = options.fetch(:add_to, true)
|
28
|
+
return_method = options.fetch(:return_method, false)
|
29
|
+
|
30
|
+
new_eigenmethod = eigenmethod.dup
|
31
|
+
|
32
|
+
ivar_callee = receiver
|
33
|
+
ivar_callee.instance_variable_set(:@proxy, proxy)
|
34
|
+
new_eigenmethod.instance_variable_set(:@callee,ivar_callee)
|
35
|
+
new_eigenmethod.init_klass_on_receiver(obj) if obj
|
36
|
+
|
37
|
+
if add_to_luggage
|
38
|
+
Terminal.luggage.delete(eigenmethod)
|
39
|
+
Terminal.luggage << new_eigenmethod
|
40
|
+
end
|
41
|
+
|
42
|
+
return new_eigenmethod if return_method
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
File without changes
|
@@ -0,0 +1,198 @@
|
|
1
|
+
module Seatbelt
|
2
|
+
|
3
|
+
# Public: Module that provides method forward declaration named :implement.
|
4
|
+
#
|
5
|
+
module Gate
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.class_eval do
|
9
|
+
include Proxy
|
10
|
+
extend ImplementationCallee
|
11
|
+
extend Synthesizeable
|
12
|
+
extend ClassMethods
|
13
|
+
private_class_method :implementation_methods,
|
14
|
+
:eigenmethods_class_level,
|
15
|
+
:initialize_implementation_method,
|
16
|
+
:implementation_from_superclass
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Proxy
|
21
|
+
|
22
|
+
# Public: Access the implementation class Proxy class instance.
|
23
|
+
# If there is no Proxy class instance defined, a new instance will
|
24
|
+
# be initialized.
|
25
|
+
#
|
26
|
+
# Returns the proxy class instance.
|
27
|
+
def proxy_object
|
28
|
+
@proxy
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
module ImplementationCallee
|
34
|
+
def mark_as_instance_implementation
|
35
|
+
lambda do |implementation_method, name|
|
36
|
+
config = implementation_method.values.pop
|
37
|
+
method = self.instance_method(name).bind(self.new)
|
38
|
+
config[:method] = method
|
39
|
+
implement(name, config)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def mark_as_class_implementation
|
44
|
+
lambda do |implementation_method, name|
|
45
|
+
config = implementation_method.values.pop
|
46
|
+
method = name.to_sym#bind(self)
|
47
|
+
config[:method] = method
|
48
|
+
config[:type] = :class
|
49
|
+
implement(name, config)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
module ClassMethods
|
55
|
+
include Gate::Proxy
|
56
|
+
include Gate::Implementation
|
57
|
+
# Internal: Collection of implementation methods configurations defined
|
58
|
+
# with the #implement_class directive.
|
59
|
+
def implementation_methods
|
60
|
+
@impl_methods ||= []
|
61
|
+
end
|
62
|
+
|
63
|
+
def implementation_class_methods
|
64
|
+
@implementation_class_methods ||= []
|
65
|
+
end
|
66
|
+
|
67
|
+
def singleton_method_added(name)
|
68
|
+
implementation_method = implementation_class_methods.detect do |method_config|
|
69
|
+
name.in?(method_config.keys)
|
70
|
+
end
|
71
|
+
if implementation_method
|
72
|
+
mark_as_class_implementation.call(implementation_method, name)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Public: Ruby hook to check if a method that is added to the class was
|
77
|
+
# defined with the #implement_class directive. If so, it calls the
|
78
|
+
# #implement method. For further information see their method documention.
|
79
|
+
#
|
80
|
+
# name - the method name as Symbol
|
81
|
+
def method_added(name)
|
82
|
+
initialize_implementation_method(name)
|
83
|
+
end
|
84
|
+
|
85
|
+
def initialize_implementation_method(name)
|
86
|
+
implementation_method = implementation_methods.detect do |method_config|
|
87
|
+
name.in?(method_config.keys)
|
88
|
+
end
|
89
|
+
if implementation_method
|
90
|
+
mark_as_instance_implementation.call(implementation_method, name)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def implementation_from_superclass(superclass_method, config)
|
95
|
+
method = self.superclass.instance_method(superclass_method).bind(self.new)
|
96
|
+
config[:method] = method
|
97
|
+
implement(superclass_method,config)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Public: Adds a method forward declaration object to a method config
|
101
|
+
# stack in Seatbelt::Terminal#luggage.
|
102
|
+
#
|
103
|
+
# *args - An argument list containing:
|
104
|
+
# * method - The method name that should be forwarded (or marked
|
105
|
+
# as implementation of a remote method)
|
106
|
+
# * options - A options Hash to configure to which method the
|
107
|
+
# implementation should be forwarded:
|
108
|
+
# :as - A String containing the remote class'
|
109
|
+
# namespace followed by a method directive
|
110
|
+
# identifier and the remote method name
|
111
|
+
#
|
112
|
+
# Example:
|
113
|
+
#
|
114
|
+
# implement :support_agility, :as => "Rails::Conference#workshop"
|
115
|
+
#
|
116
|
+
# Forwards the implementation method support_agility to the instance
|
117
|
+
# method #workshop of the class Conference within the module Rails.
|
118
|
+
#
|
119
|
+
# implement :check_speakers, :as => "Rails::Conference.invite_speakers"
|
120
|
+
#
|
121
|
+
# Forwards the implementation method :check_speakers to the class method
|
122
|
+
# #invite_speakers of the class Conference within the module Rails.
|
123
|
+
#
|
124
|
+
# This will be private in Seatbelt 1.0.
|
125
|
+
def implement(*args)
|
126
|
+
options = args.extract_options!
|
127
|
+
method = args.pop
|
128
|
+
remote_method = options[:as]
|
129
|
+
delegated_method = options.fetch(:delegated,false)
|
130
|
+
|
131
|
+
method_scope = :class if remote_method.include?(".")
|
132
|
+
method_scope = :instance if remote_method.include?("#")
|
133
|
+
directive = Seatbelt::GateConfig.method_directives[method_scope]
|
134
|
+
scope_chain = remote_method.split(directive)
|
135
|
+
remote_method = scope_chain.pop.to_sym
|
136
|
+
|
137
|
+
namespace = scope_chain.shift
|
138
|
+
type = options.fetch(:type, :instance)
|
139
|
+
|
140
|
+
receiver = self
|
141
|
+
|
142
|
+
method_proxy = Seatbelt::Eigenmethod.new
|
143
|
+
method_proxy.method = method
|
144
|
+
method_proxy.scope_level = method_scope
|
145
|
+
method_proxy.namespace = namespace
|
146
|
+
method_proxy.implemented_as = remote_method
|
147
|
+
method_proxy.receiver = receiver
|
148
|
+
method_proxy.method_implementation_type = type
|
149
|
+
method_proxy.delegated = delegated_method
|
150
|
+
#method_proxy.arity = method.arity
|
151
|
+
|
152
|
+
|
153
|
+
|
154
|
+
if method_scope.eql?(:instance)
|
155
|
+
method = instance_method(method)
|
156
|
+
method_proxy.arity = method.arity
|
157
|
+
else
|
158
|
+
method_proxy = eigenmethods_class_level(namespace,method_proxy)
|
159
|
+
end
|
160
|
+
Terminal.luggage << method_proxy
|
161
|
+
end
|
162
|
+
|
163
|
+
# Internal: Defines the Eigenclass method proxy object.
|
164
|
+
#
|
165
|
+
# This is only called if an implementation class implements a class
|
166
|
+
# method of its API class. Adds the method proxy to the eigenclass
|
167
|
+
# eigenmethods bucket.
|
168
|
+
#
|
169
|
+
# namespace - The API class name
|
170
|
+
# method_proxy - The MethodProxy skeleton created by #implement
|
171
|
+
#
|
172
|
+
# Returns the method proxy.
|
173
|
+
def eigenmethods_class_level(namespace,method_proxy)
|
174
|
+
receiver = self
|
175
|
+
options = { :eigenmethod => method_proxy,
|
176
|
+
:receiver => receiver,
|
177
|
+
:add_to => false,
|
178
|
+
:return_method => true
|
179
|
+
}
|
180
|
+
proxy = Seatbelt::Proxy.new
|
181
|
+
method_proxy = Seatbelt::EigenmethodProxy.set(proxy, options)
|
182
|
+
klass = Module.const_get(method_proxy.namespace)
|
183
|
+
|
184
|
+
callee = method_proxy.instance_variable_get(:@callee)
|
185
|
+
method_proxy.init_klass_on_receiver(klass)
|
186
|
+
implementation_type = method_proxy.instance_variable_get(:@method_implementation_type)
|
187
|
+
if implementation_type.eql?(:instance)
|
188
|
+
method_proxy.arity = callee.instance_method(method_proxy.method).arity
|
189
|
+
else
|
190
|
+
method_proxy.arity = callee.method(method_proxy.method).arity
|
191
|
+
end
|
192
|
+
klass.eigenmethods << method_proxy
|
193
|
+
return method_proxy
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|