ruby_decorators 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ .DS_Store
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
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,12 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs.push 'lib'
8
+ t.test_files = FileList['spec/**/*_spec.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => :test
@@ -0,0 +1,9 @@
1
+ class RubyDecorator
2
+ def self.+@
3
+ RubyDecorators::Stack.decorators << self
4
+ end
5
+
6
+ def +@
7
+ RubyDecorators::Stack.decorators << self
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module RubyDecorators
2
+ class Stack
3
+ def self.decorators
4
+ @decorators ||= []
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module RubyDecorators
2
+ VERSION = "0.0.1"
3
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/spec'
3
+ require 'pry'
4
+
5
+ require File.expand_path('../../lib/ruby_decorators', __FILE__)
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