metafun 0.1.0 → 0.2.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.
- data/README.rdoc +69 -55
- data/features/delegator.feature +19 -48
- data/features/steps/delegator.rb +64 -64
- data/features/steps/switchmaker.rb +136 -136
- data/features/support/env.rb +1 -1
- data/features/switchmaker.feature +32 -32
- data/lib/metafun/delegator.rb +15 -11
- data/lib/metafun/switchmaker.rb +33 -33
- data/lib/metafun/version.rb +3 -3
- data/spec/metafun/adapter_spec.rb +25 -0
- data/spec/metafun/delegator_spec.rb +52 -0
- data/test/simple-test.rb +14 -14
- metadata +10 -9
data/README.rdoc
CHANGED
@@ -1,55 +1,69 @@
|
|
1
|
-
= Metafun
|
2
|
-
|
3
|
-
A library for extending Ruby native metaprogramming capabilities
|
4
|
-
|
5
|
-
== Install
|
6
|
-
|
7
|
-
gem install metafun
|
8
|
-
|
9
|
-
== Usage
|
10
|
-
|
11
|
-
=== Delegator
|
12
|
-
|
13
|
-
Delegator delegates easily methods from a given module into a target object. The delegated methods have private access to the original module properties. Its main purpose is to easy deploy DSLs
|
14
|
-
|
15
|
-
require "metafun/delegator"
|
16
|
-
|
17
|
-
extend Metafun::Delegator
|
18
|
-
|
19
|
-
module TheModule
|
20
|
-
@@local_var = "Hello delegation"
|
21
|
-
def self.take_action
|
22
|
-
@@local_var
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
delegate TheModule, :take_action
|
27
|
-
|
28
|
-
puts take_action # At this stage, this is exactly the same
|
29
|
-
# as calling TheModule.take_action
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
#
|
50
|
-
Klass.cache
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
1
|
+
= Metafun
|
2
|
+
|
3
|
+
A library for extending Ruby native metaprogramming capabilities
|
4
|
+
|
5
|
+
== Install
|
6
|
+
|
7
|
+
gem install metafun
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
=== Delegator
|
12
|
+
|
13
|
+
Delegator delegates easily methods from a given module into a target object. The delegated methods have private access to the original module properties. Its main purpose is to easy deploy DSLs
|
14
|
+
|
15
|
+
require "metafun/delegator"
|
16
|
+
|
17
|
+
extend Metafun::Delegator
|
18
|
+
|
19
|
+
module TheModule
|
20
|
+
@@local_var = "Hello delegation"
|
21
|
+
def self.take_action
|
22
|
+
@@local_var
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
delegate TheModule, :take_action
|
27
|
+
|
28
|
+
puts take_action # At this stage, this is exactly the same
|
29
|
+
# as calling TheModule.take_action
|
30
|
+
|
31
|
+
Why Delegator and not just <tt>include TheModule</tt>? Because for most non-trivial
|
32
|
+
DSLs, you want to keep an internal state in the module object, and is not a good
|
33
|
+
idea to store the internal state on Object:main. You might as well wish to disable
|
34
|
+
the DSL API to stop pollution of the default namespace, and it should be possible
|
35
|
+
to do that transparently.
|
36
|
+
|
37
|
+
Inspired in Sinatra's Delegator.
|
38
|
+
|
39
|
+
=== Switch Maker
|
40
|
+
|
41
|
+
Switch Maker makes a friendly semantic switch out of a symbol. For example
|
42
|
+
|
43
|
+
require "metafun/switchmaker"
|
44
|
+
|
45
|
+
class Klass
|
46
|
+
switch :cache
|
47
|
+
end
|
48
|
+
|
49
|
+
# Default is false
|
50
|
+
Klass.cache? # > false
|
51
|
+
|
52
|
+
# This is how you set it. It accepts :on/:off, :yes/:no,
|
53
|
+
# true/false, 1/0...
|
54
|
+
Klass.cache :on
|
55
|
+
Klass.cache? # > true
|
56
|
+
|
57
|
+
# ... and procs
|
58
|
+
Klass.cache lambda { false }
|
59
|
+
Klass.cache? # > false
|
60
|
+
|
61
|
+
== Kitchen List
|
62
|
+
|
63
|
+
* Delegator should work aswell with Singletons and make-instance-and-die classes.
|
64
|
+
* Make specs instead of features
|
65
|
+
* Switch Maker should accept blocks, not just procs
|
66
|
+
|
67
|
+
Copyright 2011 Xavier Via
|
68
|
+
|
69
|
+
GPL License
|
data/features/delegator.feature
CHANGED
@@ -1,48 +1,19 @@
|
|
1
|
-
Feature: Delegate Module or Class methods to main Object
|
2
|
-
In order to create DSLs from modules
|
3
|
-
As a gem developer
|
4
|
-
I want to delegate their methods to main Object
|
5
|
-
|
6
|
-
Scenario: Delegate a
|
7
|
-
Given a module with the :
|
8
|
-
And I included the Delegator in the class
|
9
|
-
When I delegate :
|
10
|
-
And I execute :
|
11
|
-
Then I should get "Hello
|
12
|
-
|
13
|
-
Scenario:
|
14
|
-
Given a module with the :
|
15
|
-
And I
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
Scenario: Delegate into a class a method that receives a block
|
21
|
-
Given a module with the :with_block method that receives a block and returns its result
|
22
|
-
And I included the Delegator in the class
|
23
|
-
When I delegate :with_block into the class
|
24
|
-
And I execute :with_block in the class sending a block that returns "Hello Block!"
|
25
|
-
Then I should get "Hello Block!"
|
26
|
-
|
27
|
-
Scenario: Delegate into an object a method that receives a block
|
28
|
-
Given a module with the :with_block method that receives a block and returns its result
|
29
|
-
And I included the Delegator in the object
|
30
|
-
When I delegate :with_block into the object
|
31
|
-
And I execute :with_block in the object sending a block that returns "Hello Block!"
|
32
|
-
Then I should get "Hello Block!"
|
33
|
-
|
34
|
-
Scenario: Check that delegated method have local access to module properties
|
35
|
-
Given a module with the :local_check method that returns @@local_var
|
36
|
-
And the module @@local_var = "I am a local var, cheers!"
|
37
|
-
And I included the Delegator in the class
|
38
|
-
When I delegate :local_check into the class
|
39
|
-
And I execute :local_check in the class
|
40
|
-
Then I should get "I am a local var, cheers!"
|
41
|
-
|
42
|
-
Scenario: Same as above, in an object
|
43
|
-
Given a module with the :local_check method that returns @@local_var
|
44
|
-
And the module @@local_var = "I am a local var, cheers!"
|
45
|
-
And I included the Delegator in the object
|
46
|
-
When I delegate :local_check into the object
|
47
|
-
And I execute :local_check in the object
|
48
|
-
Then I should get "I am a local var, cheers!"
|
1
|
+
Feature: Delegate Module or Class methods to main Object
|
2
|
+
In order to create DSLs from modules
|
3
|
+
As a gem developer
|
4
|
+
I want to delegate their methods to main Object
|
5
|
+
|
6
|
+
Scenario: Delegate into a class a method that receives a block
|
7
|
+
Given a module with the :with_block method that receives a block and returns its result
|
8
|
+
And I included the Delegator in the class
|
9
|
+
When I delegate :with_block into the class
|
10
|
+
And I execute :with_block in the class sending a block that returns "Hello Block!"
|
11
|
+
Then I should get "Hello Block!"
|
12
|
+
|
13
|
+
Scenario: Check that delegated method have local access to module properties
|
14
|
+
Given a module with the :local_check method that returns @@local_var
|
15
|
+
And the module @@local_var = "I am a local var, cheers!"
|
16
|
+
And I included the Delegator in the class
|
17
|
+
When I delegate :local_check into the class
|
18
|
+
And I execute :local_check in the class
|
19
|
+
Then I should get "I am a local var, cheers!"
|
data/features/steps/delegator.rb
CHANGED
@@ -1,65 +1,65 @@
|
|
1
|
-
# Given
|
2
|
-
Given /a module with the :(.+?) method which returns "(.+?)"$/ do |method, what|
|
3
|
-
@the_module = Module.new
|
4
|
-
@the_module.module_eval "def self.#{method}; return '#{what}'; end"
|
5
|
-
end
|
6
|
-
|
7
|
-
Given /a module with the :with_block method that receives a block and returns its result/ do
|
8
|
-
@the_module = Module.new do
|
9
|
-
def self.with_block(&block)
|
10
|
-
return yield block
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
Given /a module with the :local_check method that returns @@local_var/ do
|
16
|
-
@the_module = Module.new do
|
17
|
-
def self.local_check
|
18
|
-
@@local_var
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
Given /the module @@local_var = "(.+?)"/ do |text|
|
24
|
-
@the_module.module_eval "@@local_var = '#{text}'"
|
25
|
-
end
|
26
|
-
|
27
|
-
Given /I included the Delegator in the class/ do
|
28
|
-
@the_class = Class.new
|
29
|
-
@the_class.extend Metafun::Delegator
|
30
|
-
end
|
31
|
-
|
32
|
-
Given /I included the Delegator in the object/ do
|
33
|
-
@the_object = Object.new
|
34
|
-
@the_object.extend Metafun::Delegator
|
35
|
-
end
|
36
|
-
|
37
|
-
# When
|
38
|
-
When /I delegate :(.+?) into the class/ do |method_name|
|
39
|
-
@the_class.delegate @the_module, method_name.to_sym
|
40
|
-
end
|
41
|
-
|
42
|
-
When /I delegate :(.+?) into the object/ do |method_name|
|
43
|
-
@the_object.delegate @the_module, method_name.to_sym
|
44
|
-
end
|
45
|
-
|
46
|
-
When /I execute :(.+?) in the class$/ do |method_name|
|
47
|
-
@the_result = @the_class.send method_name.to_sym
|
48
|
-
end
|
49
|
-
|
50
|
-
When /I execute :(.+?) in the object$/ do |method_name|
|
51
|
-
@the_result = @the_object.send method_name.to_sym
|
52
|
-
end
|
53
|
-
|
54
|
-
When /I execute :(.+?) in the class sending a block that returns "(.+?)"$/ do |method_name, return_value|
|
55
|
-
@the_result = @the_class.send method_name.to_sym do return_value end
|
56
|
-
end
|
57
|
-
|
58
|
-
When /I execute :(.+?) in the object sending a block that returns "(.+?)"$/ do |method_name, return_value|
|
59
|
-
@the_result = @the_object.send method_name.to_sym do return_value end
|
60
|
-
end
|
61
|
-
|
62
|
-
# Then
|
63
|
-
Then /I should get "(.+?)"$/ do |result|
|
64
|
-
@the_result.should == result
|
1
|
+
# Given
|
2
|
+
Given /a module with the :(.+?) method which returns "(.+?)"$/ do |method, what|
|
3
|
+
@the_module = Module.new
|
4
|
+
@the_module.module_eval "def self.#{method}; return '#{what}'; end"
|
5
|
+
end
|
6
|
+
|
7
|
+
Given /a module with the :with_block method that receives a block and returns its result/ do
|
8
|
+
@the_module = Module.new do
|
9
|
+
def self.with_block(&block)
|
10
|
+
return yield block
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Given /a module with the :local_check method that returns @@local_var/ do
|
16
|
+
@the_module = Module.new do
|
17
|
+
def self.local_check
|
18
|
+
@@local_var
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Given /the module @@local_var = "(.+?)"/ do |text|
|
24
|
+
@the_module.module_eval "@@local_var = '#{text}'"
|
25
|
+
end
|
26
|
+
|
27
|
+
Given /I included the Delegator in the class/ do
|
28
|
+
@the_class = Class.new
|
29
|
+
@the_class.extend Metafun::Delegator
|
30
|
+
end
|
31
|
+
|
32
|
+
Given /I included the Delegator in the object/ do
|
33
|
+
@the_object = Object.new
|
34
|
+
@the_object.extend Metafun::Delegator
|
35
|
+
end
|
36
|
+
|
37
|
+
# When
|
38
|
+
When /I delegate :(.+?) into the class/ do |method_name|
|
39
|
+
@the_class.delegate @the_module, method_name.to_sym
|
40
|
+
end
|
41
|
+
|
42
|
+
When /I delegate :(.+?) into the object/ do |method_name|
|
43
|
+
@the_object.delegate @the_module, method_name.to_sym
|
44
|
+
end
|
45
|
+
|
46
|
+
When /I execute :(.+?) in the class$/ do |method_name|
|
47
|
+
@the_result = @the_class.send method_name.to_sym
|
48
|
+
end
|
49
|
+
|
50
|
+
When /I execute :(.+?) in the object$/ do |method_name|
|
51
|
+
@the_result = @the_object.send method_name.to_sym
|
52
|
+
end
|
53
|
+
|
54
|
+
When /I execute :(.+?) in the class sending a block that returns "(.+?)"$/ do |method_name, return_value|
|
55
|
+
@the_result = @the_class.send method_name.to_sym do return_value end
|
56
|
+
end
|
57
|
+
|
58
|
+
When /I execute :(.+?) in the object sending a block that returns "(.+?)"$/ do |method_name, return_value|
|
59
|
+
@the_result = @the_object.send method_name.to_sym do return_value end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Then
|
63
|
+
Then /I should get "(.+?)"$/ do |result|
|
64
|
+
@the_result.should == result
|
65
65
|
end
|
@@ -1,137 +1,137 @@
|
|
1
|
-
module Trying
|
2
|
-
end
|
3
|
-
|
4
|
-
Given /^the class (.*?)$/ do |class_name|
|
5
|
-
@class_name = class_name
|
6
|
-
Trying.const_set(@class_name, Class.new)
|
7
|
-
end
|
8
|
-
|
9
|
-
When /^I add the switch :([^\s]*?)$/ do |switch_name|
|
10
|
-
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
11
|
-
end
|
12
|
-
|
13
|
-
When /^I add the switch :([^\s]*?) default in true$/ do |switch_name|
|
14
|
-
Trying.const_get(@class_name).class_eval do
|
15
|
-
switch switch_name.to_sym, true
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
When /^I set :(.+?) to be a proc$/ do |switch_name|
|
20
|
-
@proc = proc { true }
|
21
|
-
Trying.const_get( @class_name ).class_variable_set(
|
22
|
-
:"@@#{switch_name}", false )
|
23
|
-
|
24
|
-
Trying.const_get( @class_name ).send( switch_name.to_sym, @proc )
|
25
|
-
end
|
26
|
-
|
27
|
-
Then /^:(.+?) should return the same as the proc$/ do |question_name|
|
28
|
-
Trying.const_get( @class_name )
|
29
|
-
.send( question_name.to_sym ).should == @proc.call
|
30
|
-
end
|
31
|
-
|
32
|
-
Then /^the var :(.*?) should be defined and false \(default\)$/ do
|
33
|
-
|var_name|
|
34
|
-
|
35
|
-
Trying.const_get(@class_name).class_eval do
|
36
|
-
class_variable_defined?(var_name.to_sym).should == true
|
37
|
-
class_variable_get(var_name.to_sym).should == false
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
Then /^the var :(.*?) should be defined and true$/ do
|
42
|
-
|var_name|
|
43
|
-
|
44
|
-
Trying.const_get(@class_name).class_eval do
|
45
|
-
class_variable_defined?(var_name.to_sym).should == true
|
46
|
-
class_variable_get(var_name.to_sym).should == true
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
Then /^:(.+?) should return true$/ do |question_name|
|
51
|
-
Trying.const_get(@class_name).send(question_name).should == true
|
52
|
-
end
|
53
|
-
|
54
|
-
Then /^the method :(.+?) should be public$/ do |method_name|
|
55
|
-
Trying.const_get(@class_name).class_eval do
|
56
|
-
public_class_method(method_name.to_sym)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
Then /^:(.+?) should return (.*?) when :(.+?) called with :(.+?)$/ do
|
61
|
-
|question_name, return_value, switch_name, argument|
|
62
|
-
|
63
|
-
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
64
|
-
|
65
|
-
value = true if return_value == "true"
|
66
|
-
value = false if return_value == "false"
|
67
|
-
|
68
|
-
# Set it in true if expecting a false
|
69
|
-
if value == false
|
70
|
-
Trying.const_get(@class_name).class_eval do
|
71
|
-
class_variable_set :"@@#{switch_name}", true
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
Trying.const_get(@class_name).send switch_name.to_sym, argument.to_sym
|
76
|
-
Trying.const_get(@class_name).send(question_name).should == value
|
77
|
-
end
|
78
|
-
|
79
|
-
Then /^:(.+?) should return (.*?) when :(.+?) called with 1$/ do
|
80
|
-
|question_name, return_value, switch_name|
|
81
|
-
|
82
|
-
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
83
|
-
|
84
|
-
Trying.const_get(@class_name).send switch_name.to_sym, 1
|
85
|
-
Trying.const_get(@class_name).send(question_name).should == true
|
86
|
-
end
|
87
|
-
|
88
|
-
Then /^:(.+?) should return (.*?) when :(.+?) called with true$/ do
|
89
|
-
|question_name, return_value, switch_name|
|
90
|
-
|
91
|
-
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
92
|
-
|
93
|
-
Trying.const_get(@class_name).send switch_name.to_sym, true
|
94
|
-
Trying.const_get(@class_name).send(question_name).should == true
|
95
|
-
end
|
96
|
-
|
97
|
-
Then /^:(.+?) should return (.*?) when :(.+?) called with 0$/ do
|
98
|
-
|question_name, return_value, switch_name|
|
99
|
-
|
100
|
-
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
101
|
-
|
102
|
-
Trying.const_get(@class_name).send switch_name.to_sym, 0
|
103
|
-
Trying.const_get(@class_name).send(question_name).should == false
|
104
|
-
end
|
105
|
-
|
106
|
-
Then /^:(.+?) should return (.*?) when :(.+?) called with false$/ do
|
107
|
-
|question_name, return_value, switch_name|
|
108
|
-
|
109
|
-
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
110
|
-
|
111
|
-
Trying.const_get(@class_name).send switch_name.to_sym, false
|
112
|
-
Trying.const_get(@class_name).send(question_name).should == false
|
113
|
-
end
|
114
|
-
|
115
|
-
Then /^:(.+?) should raise ArgumentError when called with Hash$/ do
|
116
|
-
|switch_name|
|
117
|
-
|
118
|
-
expect {
|
119
|
-
Trying.const_get(@class_name).send switch_name.to_sym, Hash.new
|
120
|
-
}.to raise_error( ArgumentError )
|
121
|
-
end
|
122
|
-
|
123
|
-
Then /^:(.+?) should raise ArgumentError when called with Array$/ do
|
124
|
-
|switch_name|
|
125
|
-
|
126
|
-
expect {
|
127
|
-
Trying.const_get(@class_name).send switch_name.to_sym, Array.new
|
128
|
-
}.to raise_error( ArgumentError )
|
129
|
-
end
|
130
|
-
|
131
|
-
Then /^:(.+?) should raise ArgumentError when called with String$/ do
|
132
|
-
|switch_name|
|
133
|
-
|
134
|
-
expect {
|
135
|
-
Trying.const_get(@class_name).send switch_name.to_sym, String.new
|
136
|
-
}.to raise_error( ArgumentError )
|
1
|
+
module Trying
|
2
|
+
end
|
3
|
+
|
4
|
+
Given /^the class (.*?)$/ do |class_name|
|
5
|
+
@class_name = class_name
|
6
|
+
Trying.const_set(@class_name, Class.new)
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I add the switch :([^\s]*?)$/ do |switch_name|
|
10
|
+
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^I add the switch :([^\s]*?) default in true$/ do |switch_name|
|
14
|
+
Trying.const_get(@class_name).class_eval do
|
15
|
+
switch switch_name.to_sym, true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
When /^I set :(.+?) to be a proc$/ do |switch_name|
|
20
|
+
@proc = proc { true }
|
21
|
+
Trying.const_get( @class_name ).class_variable_set(
|
22
|
+
:"@@#{switch_name}", false )
|
23
|
+
|
24
|
+
Trying.const_get( @class_name ).send( switch_name.to_sym, @proc )
|
25
|
+
end
|
26
|
+
|
27
|
+
Then /^:(.+?) should return the same as the proc$/ do |question_name|
|
28
|
+
Trying.const_get( @class_name )
|
29
|
+
.send( question_name.to_sym ).should == @proc.call
|
30
|
+
end
|
31
|
+
|
32
|
+
Then /^the var :(.*?) should be defined and false \(default\)$/ do
|
33
|
+
|var_name|
|
34
|
+
|
35
|
+
Trying.const_get(@class_name).class_eval do
|
36
|
+
class_variable_defined?(var_name.to_sym).should == true
|
37
|
+
class_variable_get(var_name.to_sym).should == false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Then /^the var :(.*?) should be defined and true$/ do
|
42
|
+
|var_name|
|
43
|
+
|
44
|
+
Trying.const_get(@class_name).class_eval do
|
45
|
+
class_variable_defined?(var_name.to_sym).should == true
|
46
|
+
class_variable_get(var_name.to_sym).should == true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Then /^:(.+?) should return true$/ do |question_name|
|
51
|
+
Trying.const_get(@class_name).send(question_name).should == true
|
52
|
+
end
|
53
|
+
|
54
|
+
Then /^the method :(.+?) should be public$/ do |method_name|
|
55
|
+
Trying.const_get(@class_name).class_eval do
|
56
|
+
public_class_method(method_name.to_sym)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
Then /^:(.+?) should return (.*?) when :(.+?) called with :(.+?)$/ do
|
61
|
+
|question_name, return_value, switch_name, argument|
|
62
|
+
|
63
|
+
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
64
|
+
|
65
|
+
value = true if return_value == "true"
|
66
|
+
value = false if return_value == "false"
|
67
|
+
|
68
|
+
# Set it in true if expecting a false
|
69
|
+
if value == false
|
70
|
+
Trying.const_get(@class_name).class_eval do
|
71
|
+
class_variable_set :"@@#{switch_name}", true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
Trying.const_get(@class_name).send switch_name.to_sym, argument.to_sym
|
76
|
+
Trying.const_get(@class_name).send(question_name).should == value
|
77
|
+
end
|
78
|
+
|
79
|
+
Then /^:(.+?) should return (.*?) when :(.+?) called with 1$/ do
|
80
|
+
|question_name, return_value, switch_name|
|
81
|
+
|
82
|
+
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
83
|
+
|
84
|
+
Trying.const_get(@class_name).send switch_name.to_sym, 1
|
85
|
+
Trying.const_get(@class_name).send(question_name).should == true
|
86
|
+
end
|
87
|
+
|
88
|
+
Then /^:(.+?) should return (.*?) when :(.+?) called with true$/ do
|
89
|
+
|question_name, return_value, switch_name|
|
90
|
+
|
91
|
+
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
92
|
+
|
93
|
+
Trying.const_get(@class_name).send switch_name.to_sym, true
|
94
|
+
Trying.const_get(@class_name).send(question_name).should == true
|
95
|
+
end
|
96
|
+
|
97
|
+
Then /^:(.+?) should return (.*?) when :(.+?) called with 0$/ do
|
98
|
+
|question_name, return_value, switch_name|
|
99
|
+
|
100
|
+
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
101
|
+
|
102
|
+
Trying.const_get(@class_name).send switch_name.to_sym, 0
|
103
|
+
Trying.const_get(@class_name).send(question_name).should == false
|
104
|
+
end
|
105
|
+
|
106
|
+
Then /^:(.+?) should return (.*?) when :(.+?) called with false$/ do
|
107
|
+
|question_name, return_value, switch_name|
|
108
|
+
|
109
|
+
Trying.const_get(@class_name).class_eval { switch switch_name.to_sym }
|
110
|
+
|
111
|
+
Trying.const_get(@class_name).send switch_name.to_sym, false
|
112
|
+
Trying.const_get(@class_name).send(question_name).should == false
|
113
|
+
end
|
114
|
+
|
115
|
+
Then /^:(.+?) should raise ArgumentError when called with Hash$/ do
|
116
|
+
|switch_name|
|
117
|
+
|
118
|
+
expect {
|
119
|
+
Trying.const_get(@class_name).send switch_name.to_sym, Hash.new
|
120
|
+
}.to raise_error( ArgumentError )
|
121
|
+
end
|
122
|
+
|
123
|
+
Then /^:(.+?) should raise ArgumentError when called with Array$/ do
|
124
|
+
|switch_name|
|
125
|
+
|
126
|
+
expect {
|
127
|
+
Trying.const_get(@class_name).send switch_name.to_sym, Array.new
|
128
|
+
}.to raise_error( ArgumentError )
|
129
|
+
end
|
130
|
+
|
131
|
+
Then /^:(.+?) should raise ArgumentError when called with String$/ do
|
132
|
+
|switch_name|
|
133
|
+
|
134
|
+
expect {
|
135
|
+
Trying.const_get(@class_name).send switch_name.to_sym, String.new
|
136
|
+
}.to raise_error( ArgumentError )
|
137
137
|
end
|
data/features/support/env.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
$LOAD_PATH << File.expand_path("../../../lib", __FILE__)
|
1
|
+
$LOAD_PATH << File.expand_path("../../../lib", __FILE__)
|
2
2
|
require "metafun"
|
@@ -1,33 +1,33 @@
|
|
1
|
-
Feature: Make semantic switches for a class or module
|
2
|
-
In order to make semantic development easier
|
3
|
-
As a Ruby developer
|
4
|
-
I want to have a simple bundled switchmaker
|
5
|
-
|
6
|
-
Scenario: The var exists, and when asked in ?.. true or false
|
7
|
-
Given the class Klass
|
8
|
-
When I add the switch :my_switch
|
9
|
-
Then the var :@@my_switch should be defined and false (default)
|
10
|
-
And the method :my_switch? should be public
|
11
|
-
And :my_switch? should return true when :my_switch called with :on
|
12
|
-
And :my_switch? should return true when :my_switch called with :yes
|
13
|
-
And :my_switch? should return true when :my_switch called with 1
|
14
|
-
And :my_switch? should return true when :my_switch called with true
|
15
|
-
And :my_switch? should return false when :my_switch called with :off
|
16
|
-
And :my_switch? should return false when :my_switch called with :no
|
17
|
-
And :my_switch? should return false when :my_switch called with 0
|
18
|
-
And :my_switch? should return false when :my_switch called with false
|
19
|
-
And :my_switch? should raise ArgumentError when called with Hash
|
20
|
-
And :my_switch? should raise ArgumentError when called with Array
|
21
|
-
And :my_switch? should raise ArgumentError when called with String
|
22
|
-
|
23
|
-
Scenario: Adding a proc as switch
|
24
|
-
Given the class Klass
|
25
|
-
When I add the switch :my_switch
|
26
|
-
And I set :my_switch to be a proc
|
27
|
-
Then :my_switch? should return the same as the proc
|
28
|
-
|
29
|
-
Scenario: Setting default
|
30
|
-
Given the class Klass
|
31
|
-
When I add the switch :my_switch default in true
|
32
|
-
Then the var :@@my_switch should be defined and true
|
1
|
+
Feature: Make semantic switches for a class or module
|
2
|
+
In order to make semantic development easier
|
3
|
+
As a Ruby developer
|
4
|
+
I want to have a simple bundled switchmaker
|
5
|
+
|
6
|
+
Scenario: The var exists, and when asked in ?.. true or false
|
7
|
+
Given the class Klass
|
8
|
+
When I add the switch :my_switch
|
9
|
+
Then the var :@@my_switch should be defined and false (default)
|
10
|
+
And the method :my_switch? should be public
|
11
|
+
And :my_switch? should return true when :my_switch called with :on
|
12
|
+
And :my_switch? should return true when :my_switch called with :yes
|
13
|
+
And :my_switch? should return true when :my_switch called with 1
|
14
|
+
And :my_switch? should return true when :my_switch called with true
|
15
|
+
And :my_switch? should return false when :my_switch called with :off
|
16
|
+
And :my_switch? should return false when :my_switch called with :no
|
17
|
+
And :my_switch? should return false when :my_switch called with 0
|
18
|
+
And :my_switch? should return false when :my_switch called with false
|
19
|
+
And :my_switch? should raise ArgumentError when called with Hash
|
20
|
+
And :my_switch? should raise ArgumentError when called with Array
|
21
|
+
And :my_switch? should raise ArgumentError when called with String
|
22
|
+
|
23
|
+
Scenario: Adding a proc as switch
|
24
|
+
Given the class Klass
|
25
|
+
When I add the switch :my_switch
|
26
|
+
And I set :my_switch to be a proc
|
27
|
+
Then :my_switch? should return the same as the proc
|
28
|
+
|
29
|
+
Scenario: Setting default
|
30
|
+
Given the class Klass
|
31
|
+
When I add the switch :my_switch default in true
|
32
|
+
Then the var :@@my_switch should be defined and true
|
33
33
|
And :my_switch? should return true
|
data/lib/metafun/delegator.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
module Metafun
|
2
|
-
module Delegator
|
3
|
-
def delegate(target, *methods)
|
4
|
-
methods.each do |method|
|
5
|
-
self.class.send :define_method, method do |*a, &b|
|
6
|
-
target.send method, *a, &b
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
1
|
+
module Metafun
|
2
|
+
module Delegator
|
3
|
+
def delegate(target, *methods)
|
4
|
+
methods.each do |method|
|
5
|
+
self.class.send :define_method, method do |*a, &b|
|
6
|
+
target.send method, *a, &b
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Object
|
14
|
+
include Metafun::Delegator
|
15
|
+
end
|
data/lib/metafun/switchmaker.rb
CHANGED
@@ -1,34 +1,34 @@
|
|
1
|
-
module Metafun
|
2
|
-
module Switchmaker
|
3
|
-
def switch argument, default = false
|
4
|
-
class_variable_set :"@@#{argument}", default
|
5
|
-
class_eval <<-STRING
|
6
|
-
def self.#{argument}?
|
7
|
-
return @@#{argument}.call if @@#{argument}.kind_of? Proc
|
8
|
-
return @@#{argument}
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.#{argument} the_arg
|
12
|
-
if the_arg.kind_of? Proc
|
13
|
-
@@#{argument} = the_arg
|
14
|
-
else
|
15
|
-
case the_arg
|
16
|
-
when :on; @@#{argument} = true
|
17
|
-
when :yes; @@#{argument} = true
|
18
|
-
when 1; @@#{argument} = true
|
19
|
-
when true; @@#{argument} = true
|
20
|
-
when :off; @@#{argument} = false
|
21
|
-
when :no; @@#{argument} = false
|
22
|
-
when 0; @@#{argument} = false
|
23
|
-
when false; @@#{argument} = false
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
STRING
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class Class
|
33
|
-
include Metafun::Switchmaker
|
1
|
+
module Metafun
|
2
|
+
module Switchmaker
|
3
|
+
def switch argument, default = false
|
4
|
+
class_variable_set :"@@#{argument}", default
|
5
|
+
class_eval <<-STRING
|
6
|
+
def self.#{argument}?
|
7
|
+
return @@#{argument}.call if @@#{argument}.kind_of? Proc
|
8
|
+
return @@#{argument}
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.#{argument} the_arg
|
12
|
+
if the_arg.kind_of? Proc
|
13
|
+
@@#{argument} = the_arg
|
14
|
+
else
|
15
|
+
case the_arg
|
16
|
+
when :on; @@#{argument} = true
|
17
|
+
when :yes; @@#{argument} = true
|
18
|
+
when 1; @@#{argument} = true
|
19
|
+
when true; @@#{argument} = true
|
20
|
+
when :off; @@#{argument} = false
|
21
|
+
when :no; @@#{argument} = false
|
22
|
+
when 0; @@#{argument} = false
|
23
|
+
when false; @@#{argument} = false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
STRING
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Class
|
33
|
+
include Metafun::Switchmaker
|
34
34
|
end
|
data/lib/metafun/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Metafun
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
1
|
+
module Metafun
|
2
|
+
VERSION = "0.2.0"
|
3
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "metafun/adapter"
|
2
|
+
|
3
|
+
# Adapter should be an implementation of the Adapter Pattern,
|
4
|
+
# conceived as a Module which acts as Adapter of its Classes, either creating
|
5
|
+
# instances in regular Classes or obtaining instances in Singletons
|
6
|
+
#
|
7
|
+
# The Adapter should allow configuration in order to set which default
|
8
|
+
# message might be send in case the Adapter's method receives arguments
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# module MyModule
|
13
|
+
# self.extend Metafun::Adapter
|
14
|
+
#
|
15
|
+
# class Data
|
16
|
+
# def greet!; "Hi!"; end
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# MyModule.data.greet! # => 'Hi!'
|
21
|
+
#
|
22
|
+
# Delegator and Adapter combined make for a nice kit to deploying DSLs
|
23
|
+
#
|
24
|
+
describe Metafun::Adapter do
|
25
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "metafun/delegator"
|
2
|
+
|
3
|
+
describe Metafun::Delegator do
|
4
|
+
describe "#delegate" do
|
5
|
+
it "should complain if the first argument is nil or something" do
|
6
|
+
obj = mock "object"
|
7
|
+
obj.extend Metafun::Delegator
|
8
|
+
expect { obj.delegate
|
9
|
+
}.to raise_error ArgumentError
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should define a new method in the Singleton class of self" do
|
13
|
+
obj = mock "object"
|
14
|
+
target = mock "target"
|
15
|
+
obj.extend Metafun::Delegator
|
16
|
+
obj.delegate target, :greet
|
17
|
+
obj.should respond_to :greet
|
18
|
+
end
|
19
|
+
|
20
|
+
context "the target has an implementation of the message" do
|
21
|
+
before do
|
22
|
+
@target = mock "target"
|
23
|
+
@target.stub( :greet ).and_return "Hi!"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return the same the message called on the target and on self" do
|
27
|
+
obj = mock "self"
|
28
|
+
obj.extend Metafun::Delegator
|
29
|
+
obj.delegate @target, :greet
|
30
|
+
obj.greet.should == @target.greet
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have local access to the target's properties"
|
34
|
+
|
35
|
+
it "should redirect arguments to the target"
|
36
|
+
|
37
|
+
it "should redirect blocks to the target"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should do fine on multiple method calls"
|
41
|
+
|
42
|
+
it "should be injected in Object" do # This is calling for a Feature!
|
43
|
+
obj = Object.new
|
44
|
+
obj.should respond_to :delegate
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should be the :delegate from Metafun::Delegator which is in Object" do
|
48
|
+
obj = Object.new
|
49
|
+
obj.method( :delegate ).owner.should == Metafun::Delegator
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/test/simple-test.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
require "metafun/delegator"
|
2
|
-
|
3
|
-
extend Metafun::Delegator
|
4
|
-
|
5
|
-
module TheModule
|
6
|
-
@@local_var = "Hello delegation"
|
7
|
-
def self.take_action
|
8
|
-
@@local_var
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
delegate TheModule, :take_action
|
13
|
-
|
14
|
-
puts take_action # At this stage, this is exactly the same
|
1
|
+
require "metafun/delegator"
|
2
|
+
|
3
|
+
extend Metafun::Delegator
|
4
|
+
|
5
|
+
module TheModule
|
6
|
+
@@local_var = "Hello delegation"
|
7
|
+
def self.take_action
|
8
|
+
@@local_var
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
delegate TheModule, :take_action
|
13
|
+
|
14
|
+
puts take_action # At this stage, this is exactly the same
|
15
15
|
# as calling TheModule.take_action
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metafun
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
13
|
-
default_executable:
|
12
|
+
date: 2011-11-17 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: cucumber
|
17
|
-
requirement: &
|
16
|
+
requirement: &12795360 !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ! '>='
|
@@ -22,10 +21,10 @@ dependencies:
|
|
22
21
|
version: '0'
|
23
22
|
type: :development
|
24
23
|
prerelease: false
|
25
|
-
version_requirements: *
|
24
|
+
version_requirements: *12795360
|
26
25
|
- !ruby/object:Gem::Dependency
|
27
26
|
name: rspec
|
28
|
-
requirement: &
|
27
|
+
requirement: &12794040 !ruby/object:Gem::Requirement
|
29
28
|
none: false
|
30
29
|
requirements:
|
31
30
|
- - ! '>='
|
@@ -33,7 +32,7 @@ dependencies:
|
|
33
32
|
version: '0'
|
34
33
|
type: :development
|
35
34
|
prerelease: false
|
36
|
-
version_requirements: *
|
35
|
+
version_requirements: *12794040
|
37
36
|
description: A library for extending Ruby native metaprogramming capabilities
|
38
37
|
email:
|
39
38
|
- xavier.via.canel@gmail.com
|
@@ -55,8 +54,9 @@ files:
|
|
55
54
|
- lib/metafun/switchmaker.rb
|
56
55
|
- lib/metafun/version.rb
|
57
56
|
- metafun.gemspec
|
57
|
+
- spec/metafun/adapter_spec.rb
|
58
|
+
- spec/metafun/delegator_spec.rb
|
58
59
|
- test/simple-test.rb
|
59
|
-
has_rdoc: true
|
60
60
|
homepage: ''
|
61
61
|
licenses: []
|
62
62
|
post_install_message:
|
@@ -77,8 +77,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
77
|
version: '0'
|
78
78
|
requirements: []
|
79
79
|
rubyforge_project: metafun
|
80
|
-
rubygems_version: 1.
|
80
|
+
rubygems_version: 1.8.10
|
81
81
|
signing_key:
|
82
82
|
specification_version: 3
|
83
83
|
summary: A library for extending Ruby native metaprogramming capabilities
|
84
84
|
test_files: []
|
85
|
+
has_rdoc:
|