mar 0.2 → 1.0.1
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.md +28 -9
- data/lib/mar/mar.rb +4 -4
- data/lib/mar/version.rb +1 -1
- data/spec/test_mar.rb +26 -7
- metadata +1 -1
data/README.md
CHANGED
@@ -2,8 +2,8 @@ MAR
|
|
2
2
|
===
|
3
3
|
|
4
4
|
Inspired by [this blog post][ruby-decorators], I started looking into what it
|
5
|
-
might actually take to implement it. Turns out, it can be done
|
6
|
-
|
5
|
+
might actually take to implement it. Turns out, it can be done with just a few
|
6
|
+
methods tacked onto `Class`. It relies exclusively on Ruby Procs.
|
7
7
|
|
8
8
|
Examble
|
9
9
|
=======
|
@@ -11,21 +11,31 @@ Examble
|
|
11
11
|
```ruby
|
12
12
|
require 'mar'
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
# a decorator function *returns* a lambda. methods aren't first-class in Ruby,
|
15
|
+
# so this is just how it's got to be. On the other hand, it makes it very easy
|
16
|
+
# to accept options and use those in the method decorator!
|
17
|
+
def decorator(name)
|
18
|
+
lambda { |original, arg, &blk|
|
19
|
+
original.call("MAR #{arg}! --from #{name}", &blk)
|
17
20
|
}
|
18
21
|
end
|
19
22
|
|
20
23
|
class Foo
|
21
|
-
_ decorator('foo')
|
22
|
-
def foo(one_arg)
|
23
|
-
one_arg + '
|
24
|
+
_ decorator('foo') # this gets passed in as an "option" to decorator()
|
25
|
+
def foo(one_arg) # this get called via blk.call, which manipulates one_arg before calling the original method
|
26
|
+
one_arg + ', with love'
|
24
27
|
end
|
25
28
|
|
26
|
-
def bar
|
29
|
+
def bar # this doesn't get changed at all, but let's make sure of that...
|
27
30
|
'I get no respect, I tell ya\', no respect.'
|
28
31
|
end
|
32
|
+
|
33
|
+
_ decorator('baz') # this time, let's accept a block!
|
34
|
+
def baz(one_arg)
|
35
|
+
yield
|
36
|
+
one_arg
|
37
|
+
end
|
38
|
+
|
29
39
|
end
|
30
40
|
|
31
41
|
describe "Mar" do
|
@@ -40,6 +50,15 @@ describe "Mar" do
|
|
40
50
|
it 'should NOT decorate Foo#bar' do
|
41
51
|
@foo.bar.should == 'I get no respect, I tell ya\', no respect.'
|
42
52
|
end
|
53
|
+
|
54
|
+
it 'should decorate Foo#baz and accept a block' do
|
55
|
+
two = 1
|
56
|
+
nifty = @foo.baz('is nifty') {
|
57
|
+
two = 2
|
58
|
+
}
|
59
|
+
nifty.should == 'MAR is nifty! --from baz'
|
60
|
+
two.should == 2
|
61
|
+
end
|
43
62
|
end
|
44
63
|
```
|
45
64
|
|
data/lib/mar/mar.rb
CHANGED
@@ -20,12 +20,12 @@ class Class
|
|
20
20
|
if decorators.length > 0
|
21
21
|
new_name = "marrrrrrrr_#{name}"
|
22
22
|
alias_method new_name, name
|
23
|
-
define_method(name) { |*args|
|
23
|
+
define_method(name) { |*args, &outer_block|
|
24
24
|
decorator = decorators[0]
|
25
|
-
|
26
|
-
self.send(new_name, *decorator_args, &
|
25
|
+
original = lambda{ |*decorator_args, &inner_block|
|
26
|
+
self.send(new_name, *decorator_args, &inner_block)
|
27
27
|
}
|
28
|
-
decorator.call(*args, &
|
28
|
+
decorator.call(original, *args, &outer_block)
|
29
29
|
}
|
30
30
|
end
|
31
31
|
end
|
data/lib/mar/version.rb
CHANGED
data/spec/test_mar.rb
CHANGED
@@ -1,20 +1,30 @@
|
|
1
1
|
require 'mar'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
# a decorator function *returns* a lambda. methods aren't first-class in Ruby,
|
4
|
+
# so this is just how it's got to be. On the other hand, it makes it very easy
|
5
|
+
# to accept options and use those in the method decorator!
|
6
|
+
def decorator(name)
|
7
|
+
lambda { |original, arg, &blk|
|
8
|
+
original.call("MAR #{arg}! --from #{name}", &blk)
|
6
9
|
}
|
7
10
|
end
|
8
11
|
|
9
12
|
class Foo
|
10
|
-
_ decorator('foo')
|
11
|
-
def foo(one_arg)
|
12
|
-
one_arg + '
|
13
|
+
_ decorator('foo') # this gets passed in as an "option" to decorator()
|
14
|
+
def foo(one_arg) # this get called via blk.call, which manipulates one_arg before calling the original method
|
15
|
+
one_arg + ', with love'
|
13
16
|
end
|
14
17
|
|
15
|
-
def bar
|
18
|
+
def bar # this doesn't get changed at all, but let's make sure of that...
|
16
19
|
'I get no respect, I tell ya\', no respect.'
|
17
20
|
end
|
21
|
+
|
22
|
+
_ decorator('baz') # this time, let's accept a block!
|
23
|
+
def baz(one_arg)
|
24
|
+
yield
|
25
|
+
one_arg
|
26
|
+
end
|
27
|
+
|
18
28
|
end
|
19
29
|
|
20
30
|
describe "Mar" do
|
@@ -29,4 +39,13 @@ describe "Mar" do
|
|
29
39
|
it 'should NOT decorate Foo#bar' do
|
30
40
|
@foo.bar.should == 'I get no respect, I tell ya\', no respect.'
|
31
41
|
end
|
42
|
+
|
43
|
+
it 'should decorate Foo#baz and accept a block' do
|
44
|
+
two = 1
|
45
|
+
nifty = @foo.baz('is nifty') {
|
46
|
+
two = 2
|
47
|
+
}
|
48
|
+
nifty.should == 'MAR is nifty! --from baz'
|
49
|
+
two.should == 2
|
50
|
+
end
|
32
51
|
end
|