bunraku 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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