ruby_decorators 0.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/.gitignore +18 -0
- data/Gemfile +3 -0
- data/README.md +77 -0
- data/Rakefile +12 -0
- data/lib/ruby_decorator.rb +9 -0
- data/lib/ruby_decorators/stack.rb +7 -0
- data/lib/ruby_decorators/version.rb +3 -0
- data/lib/ruby_decorators.rb +49 -0
- data/ruby_decorators.gemspec +23 -0
- data/spec/ruby_decorators_spec.rb +121 -0
- data/spec/spec_helper.rb +5 -0
- metadata +112 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Ruby Decorators
|
2
|
+
|
3
|
+
#### Ruby method decorators inspired by Python.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ruby_decorators'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ruby_decorators
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
class Batman < RubyDecorator
|
23
|
+
def call(this)
|
24
|
+
this.sub('world', 'batman')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Catwoman < RubyDecorator
|
29
|
+
def initialize(*args)
|
30
|
+
@args = args.any? ? args : ['catwoman']
|
31
|
+
end
|
32
|
+
|
33
|
+
def call(this)
|
34
|
+
this.sub('world', @args.join(' '))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class DummyClass
|
39
|
+
extend RubyDecorators
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
@greeting = 'hello world'
|
43
|
+
end
|
44
|
+
|
45
|
+
def hello_world
|
46
|
+
@greeting
|
47
|
+
end
|
48
|
+
|
49
|
+
+Batman
|
50
|
+
def hello_batman
|
51
|
+
@greeting
|
52
|
+
end
|
53
|
+
|
54
|
+
+Catwoman
|
55
|
+
def hello_catwoman
|
56
|
+
@greeting
|
57
|
+
end
|
58
|
+
|
59
|
+
+Catwoman.new('super', 'catwoman')
|
60
|
+
def hello_super_catwoman
|
61
|
+
@greeting
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
dummy = DummyClass.new
|
66
|
+
|
67
|
+
dummy.hello_world # => "hello world"
|
68
|
+
dummy.hello_batman # => "hello batman"
|
69
|
+
dummy.hello_catwoman # => "hello catwoman"
|
70
|
+
dummy.hello_super_catwoman # => "hello super catwoman"
|
71
|
+
```
|
72
|
+
|
73
|
+
## License
|
74
|
+
|
75
|
+
Copyright (c) 2012 [Fred Wu](http://fredwu.me/)
|
76
|
+
|
77
|
+
Licensed under the [MIT license](http://fredwu.mit-license.org/).
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require "ruby_decorators/version"
|
2
|
+
require "ruby_decorator"
|
3
|
+
require "ruby_decorators/stack"
|
4
|
+
|
5
|
+
module RubyDecorators
|
6
|
+
def method_added(method_name)
|
7
|
+
@decorated_methods ||= []
|
8
|
+
|
9
|
+
return if RubyDecorators::Stack.decorators.empty? ||
|
10
|
+
method_name.to_s =~ /__undecorated_/ ||
|
11
|
+
@decorated_methods.include?(method_name)
|
12
|
+
|
13
|
+
current_decorator = RubyDecorators::Stack.decorators.pop
|
14
|
+
method_visibility = detect_method_visibility(method_name)
|
15
|
+
|
16
|
+
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
17
|
+
alias_method :__undecorated_#{method_name}, :#{method_name}
|
18
|
+
|
19
|
+
@__decorators ||= {}
|
20
|
+
@__decorators["#{method_name}"] = current_decorator
|
21
|
+
|
22
|
+
#{method_visibility}
|
23
|
+
def #{method_name}(*args, &blk)
|
24
|
+
decorator = #{current_decorator}.new
|
25
|
+
decorator ||= self.class.instance_variable_get(:@__decorators)["#{method_name}"]
|
26
|
+
|
27
|
+
if args.any?
|
28
|
+
decorator.call(self.send :__undecorated_#{method_name}, *args, &blk)
|
29
|
+
else
|
30
|
+
decorator.call(self.send :__undecorated_#{method_name}, &blk)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
RUBY_EVAL
|
34
|
+
|
35
|
+
@decorated_methods << method_name
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def detect_method_visibility(method_name)
|
41
|
+
if private_method_defined?(method_name)
|
42
|
+
:private
|
43
|
+
elsif protected_method_defined?(method_name)
|
44
|
+
:protected
|
45
|
+
else
|
46
|
+
:public
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ruby_decorators/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "ruby_decorators"
|
8
|
+
gem.version = RubyDecorators::VERSION
|
9
|
+
gem.authors = ["Fred Wu"]
|
10
|
+
gem.email = ["ifredwu@gmail.com"]
|
11
|
+
gem.description = %q{Ruby method decorators inspired by Python.}
|
12
|
+
gem.summary = gem.description
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_development_dependency 'rake'
|
21
|
+
gem.add_development_dependency 'pry'
|
22
|
+
gem.add_development_dependency 'minitest'
|
23
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe RubyDecorators do
|
4
|
+
class DummyDecorator < RubyDecorator
|
5
|
+
def call(this)
|
6
|
+
'I should never be called'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Batman < RubyDecorator
|
11
|
+
def call(this)
|
12
|
+
this.sub('world', 'batman')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Catwoman < RubyDecorator
|
17
|
+
def initialize(*args)
|
18
|
+
@args = args.any? ? args : ['catwoman']
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(this)
|
22
|
+
this.sub('world', @args.join(' '))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class DummyClass
|
27
|
+
extend RubyDecorators
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@greeting = 'hello world'
|
31
|
+
end
|
32
|
+
|
33
|
+
def hello_world
|
34
|
+
@greeting
|
35
|
+
end
|
36
|
+
|
37
|
+
+Batman
|
38
|
+
def hello_public
|
39
|
+
@greeting
|
40
|
+
end
|
41
|
+
|
42
|
+
+DummyDecorator
|
43
|
+
def hello_void
|
44
|
+
@greeting
|
45
|
+
end
|
46
|
+
|
47
|
+
+Batman
|
48
|
+
def hello_with_args(arg1, arg2)
|
49
|
+
"#{@greeting} #{arg1} #{arg2}"
|
50
|
+
end
|
51
|
+
|
52
|
+
+Catwoman
|
53
|
+
def hello_catwoman
|
54
|
+
@greeting
|
55
|
+
end
|
56
|
+
|
57
|
+
+Batman
|
58
|
+
def hello_with_block(arg1, arg2, &block)
|
59
|
+
"#{@greeting} #{arg1} #{arg2} #{block.call if block_given?}"
|
60
|
+
end
|
61
|
+
|
62
|
+
+Catwoman.new('super', 'catwoman')
|
63
|
+
def hello_super_catwoman
|
64
|
+
@greeting
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
+Batman
|
70
|
+
def hello_protected
|
71
|
+
@greeting
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
+Batman
|
77
|
+
def hello_private
|
78
|
+
@greeting
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
subject { DummyClass.new }
|
83
|
+
|
84
|
+
it "#hello_world" do
|
85
|
+
subject.hello_world.must_equal 'hello world'
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "a simple decorator" do
|
89
|
+
it "decorates a public method" do
|
90
|
+
subject.hello_public.must_equal 'hello batman'
|
91
|
+
end
|
92
|
+
|
93
|
+
it "decorates a protected method" do
|
94
|
+
subject.send(:hello_protected).must_equal 'hello batman'
|
95
|
+
lambda { subject.hello_protected }.must_raise NoMethodError
|
96
|
+
end
|
97
|
+
|
98
|
+
it "decorates a private method" do
|
99
|
+
subject.send(:hello_private).must_equal 'hello batman'
|
100
|
+
lambda { subject.hello_private }.must_raise NoMethodError
|
101
|
+
end
|
102
|
+
|
103
|
+
it "decorates a method with args" do
|
104
|
+
subject.hello_with_args('how are', 'you?').must_equal 'hello batman how are you?'
|
105
|
+
end
|
106
|
+
|
107
|
+
it "decorates a method with a block" do
|
108
|
+
subject.hello_with_block('how are', 'you') { 'man?' }.must_equal 'hello batman how are you man?'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "a decorator with args" do
|
113
|
+
it "decorates without any decorator args" do
|
114
|
+
subject.hello_catwoman.must_equal 'hello catwoman'
|
115
|
+
end
|
116
|
+
|
117
|
+
it "decorate a simple method" do
|
118
|
+
subject.hello_super_catwoman.must_equal 'hello super catwoman'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby_decorators
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Fred Wu
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: pry
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: minitest
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Ruby method decorators inspired by Python.
|
63
|
+
email:
|
64
|
+
- ifredwu@gmail.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- Gemfile
|
71
|
+
- README.md
|
72
|
+
- Rakefile
|
73
|
+
- lib/ruby_decorator.rb
|
74
|
+
- lib/ruby_decorators.rb
|
75
|
+
- lib/ruby_decorators/stack.rb
|
76
|
+
- lib/ruby_decorators/version.rb
|
77
|
+
- ruby_decorators.gemspec
|
78
|
+
- spec/ruby_decorators_spec.rb
|
79
|
+
- spec/spec_helper.rb
|
80
|
+
homepage: ''
|
81
|
+
licenses: []
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
hash: -334699568952873457
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
hash: -334699568952873457
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 1.8.24
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: Ruby method decorators inspired by Python.
|
110
|
+
test_files:
|
111
|
+
- spec/ruby_decorators_spec.rb
|
112
|
+
- spec/spec_helper.rb
|