bunraku 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ class Module
2
+ def context(name, &block)
3
+ if const_defined?(name)
4
+ context_class = const_get(name)
5
+ else
6
+ context_class = Class.new
7
+ const_set(name, context_class)
8
+ context_class.module_eval do
9
+ include Bunraku::Context
10
+ end
11
+ def context_class.role(name, &block)
12
+ if const_defined?(name)
13
+ role_class = const_get(name)
14
+ else
15
+ role_class = Class.new
16
+ const_set(name, role_class)
17
+ role_class.module_eval do
18
+ include Bunraku::Role
19
+ extend Bunraku::RoleExtensions
20
+ end
21
+ end
22
+ role_class.module_eval(&block)
23
+ end
24
+ end
25
+ context_class.module_eval(&block)
26
+ end
27
+ end
28
+
29
+ class Class
30
+ def as_context
31
+ include Bunraku::Context
32
+ end
33
+ def as_role
34
+ include Bunraku::Role
35
+ extend Bunraku::RoleExtensions
36
+ end
37
+ end
@@ -0,0 +1,257 @@
1
+
2
+ =begin
3
+ Interfaces for external objects
4
+ =end
5
+ module Bunraku
6
+ module Context
7
+ def bind(&spec_block)
8
+ BindExecuter.new(self, spec_block)
9
+ end
10
+ def unbind
11
+ context = self
12
+ self.class.constants.each do |const_name|
13
+ role_list = Utils.get_role_list(context, const_name)
14
+ next unless role_list
15
+ role_list.delete_if do |role_holder|
16
+ role_holder.unbind
17
+ true
18
+ end
19
+ end
20
+ nil
21
+ end
22
+ private
23
+ def method_missing(name, *args)
24
+ role_class = Utils.get_role_class(self, name)
25
+ return super(name, *args) unless role_class
26
+ role_list_name = Utils.role_list_name(name)
27
+ unless instance_variables.include? role_list_name
28
+ instance_variable_set(role_list_name, [])
29
+ end
30
+ role_list = instance_variable_get(role_list_name)
31
+ return RoleBinder.new(self, role_list, role_class)
32
+ end
33
+ end
34
+
35
+ module Role
36
+ protected
37
+ def context
38
+ ContextProxy.new(@role_holder.context)
39
+ end
40
+ def core
41
+ @role_holder.core
42
+ end
43
+ private
44
+ def set_role_holder(role_holder)
45
+ @role_holder = role_holder
46
+ end
47
+ def method_missing(name, *args)
48
+ m = @role_holder.get_super_method(name.to_sym)
49
+ return m.call(*args) if m
50
+ super(name, *args)
51
+ end
52
+ end
53
+
54
+ class RoleBinder
55
+ def initialize(context, role_list, role_class)
56
+ @context = context
57
+ @role_list = role_list
58
+ @role_class = role_class
59
+ end
60
+ def bind(obj, &block)
61
+ role_holder = @role_list.detect do |role_holder|
62
+ role_holder.target == obj
63
+ end
64
+ unless role_holder
65
+ role = @role_class.new
66
+ role_holder = RoleHolder.new(@context, role, obj)
67
+ role_holder.bind
68
+ @role_list << role_holder
69
+ end
70
+ block.call(role_holder) if block
71
+ @role_class.requires_test(role_holder)
72
+ nil
73
+ end
74
+ def unbind(obj)
75
+ @role_list.delete_if do |role_holder|
76
+ if role_holder.target == obj
77
+ role_holder.unbind
78
+ true
79
+ else
80
+ false
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ class RoleHolder
87
+ CORE_GETTER = :__bunraku_core_get
88
+ def initialize(context, role, target)
89
+ @context = context
90
+ @role = role
91
+ @target = target
92
+ @target_mod = Module.new
93
+ @target.extend(@target_mod)
94
+ @methods = {}
95
+ @core_getter = nil
96
+ end
97
+ attr :context
98
+ attr :role
99
+ attr :target
100
+
101
+ def replace_to(role_method_name, target_method_name)
102
+ @methods[role_method_name.to_sym] = @target.method(target_method_name)
103
+ end
104
+
105
+ def def_method(name, &body)
106
+ tmpname = "__temp__" + name.to_s
107
+ @target_mod.instance_eval do
108
+ public
109
+ define_method(tmpname, &body)
110
+ end
111
+ @methods[name] = @target.method(tmpname)
112
+ @target_mod.instance_eval do
113
+ undef_method(tmpname)
114
+ end
115
+ end
116
+
117
+ def get_method(name)
118
+ name = name.to_sym
119
+ return @role.method(name) if @role.methods.include?(name.to_s)
120
+ return @methods[name] if @methods[name]
121
+ return @target.method(name) if @target.methods.include?(name.to_s)
122
+ nil
123
+ end
124
+
125
+ def get_super_method(name)
126
+ name = name.to_sym
127
+ return @methods[name] if @methods[name]
128
+ return @target.method(name) if @target.methods.include?(name.to_s)
129
+ #return @role.method(name) if @role.methods.include?(name.to_s)
130
+ nil
131
+ end
132
+
133
+ def core
134
+ return CoreProxy.new(self) if @core_getter == nil
135
+ core_holder = @core_getter.call()
136
+ if core_holder != nil
137
+ return HolderProxy.new(core_holder)
138
+ else
139
+ return CoreProxy.new(self)
140
+ end
141
+ end
142
+
143
+ def get_core
144
+ proc do
145
+ return self if @target != nil
146
+ return nil if @core_getter == nil
147
+ return @core_getter.call()
148
+ end
149
+ end
150
+
151
+ def bind
152
+ role_holder = self
153
+ @role.instance_eval do
154
+ set_role_holder(role_holder)
155
+ end
156
+ begin
157
+ @core_getter = @target.instance_eval do
158
+ send(CORE_GETTER)
159
+ end
160
+ rescue
161
+ end
162
+ @target_mod.instance_eval do
163
+ private
164
+ define_method(CORE_GETTER) do
165
+ role_holder.get_core
166
+ end
167
+ define_method(:method_missing) do |name, *args|
168
+ m = role_holder.get_method(name.to_sym)
169
+ return m.call(*args) if m
170
+ super(name, *args)
171
+ end
172
+ end
173
+ # override processing
174
+ @role.class.each_overrides do |method|
175
+ @methods[method] = @target.method(method)
176
+ @target_mod.instance_eval do
177
+ define_method(method) do |*args|
178
+ m = role_holder.get_method(method)
179
+ return m.call(*args) if m
180
+ super(*args)
181
+ end
182
+ end
183
+ end
184
+
185
+ @role.init_role if @role.methods.include?("init_role")
186
+ end
187
+
188
+ def unbind
189
+ @target_mod.instance_eval do
190
+ private
191
+ define_method(CORE_GETTER) do
192
+ super()
193
+ end
194
+ define_method(:method_missing) do |name, *args|
195
+ super(name, *args)
196
+ end
197
+ end
198
+ @target = nil
199
+ @methods = {}
200
+ end
201
+ end
202
+
203
+ module RoleExtensions
204
+ def requires(&block)
205
+ @requires = [] unless instance_variables.include? "@requires"
206
+ @requires << block
207
+ end
208
+
209
+ def override(method)
210
+ @overrides = [] unless instance_variables.include? "@overrides"
211
+ @overrides << method.to_sym
212
+ end
213
+
214
+ def requires_test(holder)
215
+ return true unless instance_variables.include? "@requires"
216
+ req = RoleRequires.new(holder)
217
+ @requires.each do |block|
218
+ block.call(req)
219
+ end
220
+ raise BindRoleError.new(req.errors) unless req.errors.empty?
221
+ end
222
+
223
+ def each_overrides(&block)
224
+ @overrides.each(&block) if instance_variables.include? "@overrides"
225
+ end
226
+ end
227
+
228
+ class RoleRequires
229
+ def initialize(holder)
230
+ @holder = holder
231
+ @errors = []
232
+ end
233
+ attr :errors
234
+
235
+ def method?(name)
236
+ unless @holder.get_method(name.to_sym)
237
+ @errors << "require method: #{name.to_s}"
238
+ end
239
+ nil
240
+ end
241
+ end
242
+
243
+ class BindExecuter
244
+ def initialize(context, spec)
245
+ @context = context
246
+ @spec = spec
247
+ end
248
+ def call(&block)
249
+ context = @context
250
+ @spec.call(context)
251
+ result = block.call()
252
+ context.unbind
253
+ result
254
+ end
255
+ end
256
+ end
257
+
@@ -0,0 +1,10 @@
1
+ module Bunraku
2
+ class BindRoleError < Exception
3
+ def initialize(errors)
4
+ @errors = errors
5
+ end
6
+ def message
7
+ @errors.join("\n")
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,121 @@
1
+
2
+ =begin
3
+ Proxies are objects for using only inside role methods.
4
+ =end
5
+ module Bunraku
6
+ class ContextProxy
7
+ def initialize(context)
8
+ @context = context
9
+ end
10
+
11
+ def method_missing(name, *args)
12
+ if @context.class.constants.include?(name.to_s)
13
+ role = @context.class.const_get(name)
14
+ return RoleProxy.new(@context, name, role)
15
+ end
16
+ sname = name.to_s.singularize.to_sym
17
+ if @context.class.constants.include?(sname.to_s)
18
+ role = @context.class.const_get(sname)
19
+ default = if args.size == 1 then args[0] else nil end
20
+ return RolesProxy.new(@context, sname, role, default) if role
21
+ end
22
+ if @context.methods.include?(name.to_s)
23
+ return @context.send(name, *args)
24
+ end
25
+ super(name, *args)
26
+ end
27
+
28
+ def eql?(o)
29
+ return false if o.class != self.class
30
+ @context == o.instance_variable_get(:@context)
31
+ end
32
+ def hash
33
+ @context.hash
34
+ end
35
+ def ==(o)
36
+ eql?(o)
37
+ end
38
+ end
39
+
40
+ class CoreProxy
41
+ def initialize(role_holder)
42
+ @role_holder = role_holder
43
+ end
44
+ private
45
+ def method_missing(name, *args)
46
+ m = @role_holder.get_super_method(name)
47
+ return m.call(*args) if m
48
+ super(name, *args)
49
+ end
50
+ end
51
+
52
+ class HolderProxy
53
+ def initialize(role_holder)
54
+ @role_holder = role_holder
55
+ end
56
+ private
57
+ def method_missing(name, *args)
58
+ m = @role_holder.get_method(name)
59
+ return m.call(*args) if m
60
+ super(name, *args)
61
+ end
62
+ end
63
+
64
+ class RoleProxyBase
65
+ def initialize(context, role_name, role_class)
66
+ @context = context
67
+ @role_name = role_name
68
+ @role_class = role_class
69
+ @role_list = Utils.get_role_list(@context, @role_name)
70
+ end
71
+ def eql?(o)
72
+ return false if o.class != self.class
73
+ context_equal = (@context == o.instance_variable_get(:@context))
74
+ role_equal = (@role_class == o.instance_variable_get(:@role_class))
75
+ context_equal and role_equal
76
+ end
77
+ def hash
78
+ (@context.hash | @role_class.hash)
79
+ end
80
+ def ==(o)
81
+ eql?(o)
82
+ end
83
+ end
84
+
85
+ class RoleProxy < RoleProxyBase
86
+ private
87
+ def method_missing(name, *args)
88
+ HolderProxy.new(@role_list[0]).send(name, *args)
89
+ end
90
+ end
91
+
92
+ class RolesProxy < RoleProxyBase
93
+ def initialize(context, role_name, role_class, default=nil)
94
+ super(context, role_name, role_class)
95
+ @default = default
96
+ end
97
+
98
+ def each(&block)
99
+ results = []
100
+ @role_list.each do |role_holder|
101
+ begin
102
+ results << block.call(HolderProxy.new(role_holder))
103
+ rescue
104
+ results << @default
105
+ end
106
+ end
107
+ end
108
+ private
109
+ def method_missing(name, *args)
110
+ results = []
111
+ @role_list.each do |role_holder|
112
+ begin
113
+ results << HolderProxy.new(role_holder).send(name, *args)
114
+ rescue
115
+ results << @default
116
+ end
117
+ end
118
+ return results
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,21 @@
1
+
2
+ module Bunraku
3
+ module Utils
4
+ def self.get_role_class(context, role_name)
5
+ context.class.const_get(role_name)
6
+ end
7
+ def self.role_class?(context, role_name, role_class)
8
+ role_class.class == Class and
9
+ role_class.include? Role and
10
+ context.instance_variables.include?(role_list_name(role_name))
11
+ end
12
+ def self.get_role_list(context, role_name)
13
+ role_class = get_role_class(context, role_name)
14
+ return nil unless role_class?(context, role_name, role_class)
15
+ context.instance_variable_get(role_list_name(role_name))
16
+ end
17
+ def self.role_list_name(role_name)
18
+ "@" + role_name.to_s
19
+ end
20
+ end
21
+ end