decorator 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/.gemtest +0 -0
- data/History.txt +3 -0
- data/Manifest.txt +8 -0
- data/README.rdoc +50 -0
- data/Rakefile +9 -0
- data/lib/decorator.rb +8 -0
- data/lib/decorator/decorator.rb +140 -0
- data/lib/decorator/kwargsable.rb +41 -0
- data/lib/decorator/only.rb +7 -0
- metadata +80 -0
data/.gemtest
ADDED
File without changes
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
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
data/lib/decorator.rb
ADDED
@@ -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
|
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: []
|