decorator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gemtest ADDED
File without changes
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ === 2012/2/24
2
+
3
+ * gem 化
data/Manifest.txt ADDED
@@ -0,0 +1,8 @@
1
+ lib/decorator.rb
2
+ lib/decorator/only.rb
3
+ lib/decorator/decorator.rb
4
+ lib/decorator/kwargsable.rb
5
+ README.rdoc
6
+ Rakefile
7
+ History.txt
8
+ Manifest.txt
data/README.rdoc ADDED
@@ -0,0 +1,50 @@
1
+ == Decorator
2
+ * http://github.com/pasberth/Decorator
3
+
4
+
5
+ == DESCRIPTION:
6
+ the Decorator make a decorator like Python.
7
+
8
+ == Usage
9
+
10
+ require 'decorator'
11
+
12
+ または
13
+
14
+ require 'decorator/only'
15
+
16
+ require 'decorator' だと Module#decorator だけでなく Module#kwargsable も一緒に使えます。
17
+ require 'decorator/only' だと Module#decorator だけがロードされます
18
+
19
+ 普通、このモジュールで使う関数はModule#decoratorのみです。
20
+ それはデコレータを作成するデコレータです。デコレータを作る場合は通常これをデコレータとします。
21
+ *example*:
22
+ class Module
23
+ decorator
24
+ def wrap func, *args, &blk
25
+ puts "wrapped!"
26
+ proc { func.call *args, &blk }
27
+
28
+ デコレータの第一引数は必ずMethodです。
29
+ この場合のwrapはデコレータとして使用できます。
30
+
31
+ class TestClass
32
+ wrap
33
+ def wrapped *args, &blk
34
+ puts "IN!"
35
+
36
+ もしデコレータに引数を渡した場合、それはすべてデコレータに一緒に渡されます。
37
+
38
+ class TestClass
39
+ wrap(*example_args)
40
+ def wrapped *args, &blk
41
+ puts "IN!"
42
+
43
+ => ↓のargsにexample_argsが渡される
44
+
45
+ def wrap func, *args, &blk
46
+ puts "wrapped!"
47
+ proc { func.call *args, &blk }
48
+
49
+ デコレータの戻り値がProcである場合、関数はそのProcに置き換えられます。
50
+ たとえばこの場合、wrappedはwrap内のprocに置き換えられます。
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require './lib/decorator'
2
+ require 'hoe'
3
+
4
+ Hoe.spec 'decorator' do
5
+ self.developer 'pasberth', 'pasberth@gmail.com'
6
+ self.rubyforge_name = self.name
7
+ self.readme_file = 'README.rdoc'
8
+ self.version = Decorator::VERSION
9
+ end
data/lib/decorator.rb ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ $:.unshift(File.dirname(__FILE__)) unless
5
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
6
+
7
+ require "decorator/only"
8
+ require "decorator/kwargsable"
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ module Decorator
5
+ VERSION = "0.0.1"
6
+ end
7
+
8
+ class Object
9
+
10
+ private
11
+
12
+ def decorators
13
+ @decorators ||= []
14
+ end
15
+
16
+ def add_decorator _f, *args, &blk
17
+ _f = case _f
18
+ when UnboundMethod then _f.bind self
19
+ when Method then _f
20
+ end
21
+ _after = ->(_func, *_args, &_blk) do # the _after is called when created the a_function
22
+ # selfがこのクラスまたはモジュールのインスタンスになるようにinstance_execなどをすること
23
+ # define_methodなどでもselfは正しくなるのでそれでok
24
+ _new_method = ->(*__args, &__blk) do # new function replaced to the a_function
25
+ _func = case _func
26
+ when UnboundMethod then _func.bind self
27
+ when Method then _func
28
+ end
29
+ res = _f.call _func, *args, &blk
30
+ if res.respond_to? :to_proc
31
+ define_singleton_method _func.name, &res
32
+ send _func.name, *__args, &__blk
33
+ elsif Method === res || UnboundMethod === res
34
+ define_singleton_method _func.name, res
35
+ send _func.name, *__args, &__blk
36
+ end
37
+ end
38
+ return _new_method
39
+ end
40
+ decorators << [_after, args, blk]
41
+ true
42
+ end
43
+
44
+ alias decoratable_original_singleton_method_added singleton_method_added
45
+
46
+ def singleton_method_added funcname
47
+ decoratable_original_singleton_method_added(funcname).tap do
48
+ next if decorators.empty?
49
+ origin = method funcname
50
+ func = origin
51
+
52
+ until decorators.empty?
53
+ decorators.pop.tap do |f, args, blk|
54
+ res = f.call func, *args, &blk
55
+ if res.respond_to? :to_proc
56
+ define_singleton_method funcname, &res
57
+ func = method func.name
58
+ elsif Method === res || UnboundMethod === res
59
+ define_singleton_method funcname, res
60
+ func = method func.name
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+
69
+ class Module
70
+ # デコレータを作成するデコレータです。デコレータを作る場合は通常これをデコレータとします。
71
+ # example:
72
+ # class Module
73
+ # decorator
74
+ # def wrap func, *args, &blk
75
+ # puts "wrapped!"
76
+ # proc { func.call *args, &blk }
77
+ # デコレータの第一引数は必ずMethodです。
78
+ # この場合のwrapはデコレータとして使用できます。
79
+ # class TestClass
80
+ # wrap
81
+ # def wrapped *args, &blk
82
+ # puts "IN!"
83
+ # もしデコレータに引数を渡した場合、それはすべてデコレータに一緒に渡されます。
84
+ # class TestClass
85
+ # wrap(*example_args)
86
+ # def wrapped *args, &blk
87
+ # puts "IN!"
88
+ # => ↓のargsにexample_argsが渡される
89
+ # def wrap func, *args, &blk
90
+ # puts "wrapped!"
91
+ # proc { func.call *args, &blk }
92
+ # デコレータの戻り値がProcである場合、関数はそのProcに置き換えられます。
93
+ # たとえばこの場合、wrappedはwrap内のprocに置き換えられます。
94
+ def decorator *args, &blk
95
+
96
+ # for example,
97
+ # class Example
98
+ # decorator
99
+ # def self.logging
100
+ # ...
101
+ #
102
+ # logging
103
+ # def a_function
104
+ # ...
105
+ after = ->(_f, *_a, &_b) do # the after is called when created the self.logging
106
+ new_method = ->(*args, &blk) do # new function replaced to the self.logging
107
+ add_decorator _f, *args, &blk
108
+ end
109
+
110
+ return new_method
111
+ end
112
+
113
+ decorators << [after, args, blk]
114
+ true
115
+ end
116
+
117
+
118
+ alias decoratable_original_method_added method_added
119
+
120
+ def method_added funcname
121
+ decoratable_original_method_added(funcname).tap do
122
+ next if decorators.empty?
123
+ origin = instance_method funcname
124
+ func = origin
125
+
126
+ until decorators.empty?
127
+ decorators.pop.tap do |f, args, blk|
128
+ res = f.call func, *args, &blk
129
+ if res.respond_to? :to_proc
130
+ define_method funcname, &res
131
+ func = instance_method func.name
132
+ elsif Method === res || UnboundMethod === res
133
+ define_method funcname, res
134
+ func = instance_method func.name
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require 'decorator/only'
5
+
6
+ class Module
7
+
8
+ decorator
9
+ def kwargsable func, default_args={}, &default_blk
10
+ params = func.parameters
11
+ params_nonblock = params.reject { |i| i[0] == :block }
12
+ xs = params_nonblock.map { |i| i[1] }
13
+ ->(*args, &blk) do
14
+
15
+ if args.last.respond_to? :to_hash
16
+ kwargs = args.pop.to_hash
17
+ else
18
+ kwargs = {}
19
+ end
20
+
21
+ args.fill nil, args.length, params_nonblock.length - args.length - 1
22
+
23
+ default_args.each do |key, default|
24
+ next unless xs.include? key
25
+ i = xs.index(key)
26
+ if args[i].nil? then args[i] = default
27
+ end
28
+ end
29
+
30
+ blk = default_blk if blk.nil?
31
+
32
+ kwargs.each do |key, arg|
33
+ next unless xs.include? key
34
+ kwargs.delete key
35
+ args[xs.index(key)] = arg
36
+ end
37
+
38
+ func.call *args, kwargs, &blk
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ $:.unshift(File.dirname File.dirname(__FILE__)) unless
5
+ $:.include?(File.dirname File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname File.dirname(__FILE__)))
6
+
7
+ require "decorator/decorator"
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: decorator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - pasberth
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rdoc
16
+ requirement: &70276038777500 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.10'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70276038777500
25
+ - !ruby/object:Gem::Dependency
26
+ name: hoe
27
+ requirement: &70276038777080 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '2.13'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70276038777080
36
+ description: the Decorator make a decorator like Python.
37
+ email:
38
+ - pasberth@gmail.com
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files:
42
+ - History.txt
43
+ - Manifest.txt
44
+ files:
45
+ - lib/decorator.rb
46
+ - lib/decorator/only.rb
47
+ - lib/decorator/decorator.rb
48
+ - lib/decorator/kwargsable.rb
49
+ - README.rdoc
50
+ - Rakefile
51
+ - History.txt
52
+ - Manifest.txt
53
+ - .gemtest
54
+ homepage: http://github.com/pasberth/Decorator
55
+ licenses: []
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --main
59
+ - README.rdoc
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project: decorator
76
+ rubygems_version: 1.8.10
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: the Decorator make a decorator like Python.
80
+ test_files: []