use 1.1.0 → 1.2.0
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/CHANGES +6 -0
- data/MANIFEST +2 -1
- data/README +9 -0
- data/lib/use.rb +67 -98
- data/test/tc_use.rb +75 -87
- data/test/test_data.rb +72 -0
- metadata +22 -17
data/CHANGES
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 1.2.0 - 24-Feb-2006
|
2
|
+
* Method is now redefined within Class instead of Module in order to make
|
3
|
+
the ability to use 'include' and 'alias' more flexible and work more nicely
|
4
|
+
together.
|
5
|
+
* Updated the test suite.
|
6
|
+
|
1
7
|
== 1.1.0 - 20-Jan-2006
|
2
8
|
* Using 'use' with no arguments is now the same as if you used 'include',
|
3
9
|
i.e. all methods are mixed in. Previously, this would not mixin any methods.
|
data/MANIFEST
CHANGED
data/README
CHANGED
@@ -53,6 +53,10 @@
|
|
53
53
|
m = MyKlass.new
|
54
54
|
m.test # "hello"
|
55
55
|
m.bar # NoMethodError
|
56
|
+
|
57
|
+
== Constants
|
58
|
+
USE_VERSION
|
59
|
+
The version of this package, returned as a String.
|
56
60
|
|
57
61
|
== Acknowledgements
|
58
62
|
Thanks go to Ara Howard for providing the original solution and to
|
@@ -62,6 +66,11 @@
|
|
62
66
|
== Known Bugs
|
63
67
|
None that I'm aware of. If you find any, please log them on the project
|
64
68
|
page at http://www.rubyforge.org/projects/shards.
|
69
|
+
|
70
|
+
== Questions?
|
71
|
+
Please post your comment or question on one of the forums on the project
|
72
|
+
page at http://www.rubyforge.org/projects/shards. Just click the 'Forums'
|
73
|
+
link.
|
65
74
|
|
66
75
|
== License
|
67
76
|
Ruby's
|
data/lib/use.rb
CHANGED
@@ -1,122 +1,91 @@
|
|
1
|
-
class
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
# use module, methods
|
6
|
-
# # or
|
7
|
-
# use module, option => value, ...
|
8
|
-
#
|
9
|
-
# The 'use' directive allows you to selectively mixin +methods+ from the
|
10
|
-
# given +module+. The +methods+ may be either strings or symbols. If
|
11
|
-
# no methods are provided then 'use' is effectively the same thing as
|
12
|
-
# 'include', i.e. all methods are mixed in.
|
13
|
-
#
|
14
|
-
# If a Hash is provided, there are three keywords available to you:
|
15
|
-
#
|
16
|
-
# * 'include'
|
17
|
-
# This option lets you specify one or more methods to explicitly include.
|
18
|
-
# If you wish to include more than one method, use an array as the value.
|
19
|
-
#
|
20
|
-
# * 'exclude'
|
21
|
-
# This option lets you specify one or more methods to explicitly exclude.
|
22
|
-
# If you wish to exclude more than one method, use an array as the value.
|
23
|
-
#
|
24
|
-
# * 'alias'
|
25
|
-
# This option lets you include a method, but as a different method name.
|
26
|
-
# Use a hash as the value to +alias+, e.g. :alias => {:old, :new, ... }.
|
27
|
-
# Using this option doubles as an explicit include, so you do not need
|
28
|
-
# to both include and alias in the same statement.
|
29
|
-
#
|
30
|
-
# Note that the original method name is NOT included if aliased this way.
|
31
|
-
#
|
32
|
-
# Also note that you cannot include and exclude in the same statement,
|
33
|
-
# or an ArgumentError is raised. You can, however, exclude and alias.
|
34
|
-
#
|
35
|
-
def use(mod, *methods)
|
36
|
-
valid = %w/include exclude alias/
|
37
|
-
included = []
|
1
|
+
class Class
|
2
|
+
USE_VERSION = '1.2.0'
|
3
|
+
def use(*args)
|
4
|
+
valid_keys = %w/include exclude alias/
|
38
5
|
excluded = []
|
6
|
+
included = []
|
39
7
|
aliased = []
|
40
8
|
|
41
|
-
|
9
|
+
mod = args.shift.clone
|
42
10
|
|
43
|
-
# If
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
methods = methods.first
|
48
|
-
methods.each{ |key, val|
|
49
|
-
unless valid.include?(key.to_s.downcase)
|
50
|
-
raise ArgumentError, "invalid key: #{key}"
|
51
|
-
end
|
11
|
+
# If no arguments follow the module name, treat it as a standard include
|
12
|
+
if args.empty?
|
13
|
+
included.concat(mod.instance_methods)
|
14
|
+
end
|
52
15
|
|
53
|
-
|
54
|
-
if val.respond_to?(:each)
|
55
|
-
val.each{ |arg| included.push(arg.to_sym) }
|
56
|
-
else
|
57
|
-
included.push(val.to_sym)
|
58
|
-
end
|
59
|
-
end
|
16
|
+
m = Module.new
|
60
17
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
18
|
+
args.each{ |arg|
|
19
|
+
if arg.kind_of?(Hash)
|
20
|
+
arg.each{ |key, val|
|
21
|
+
case key.to_s
|
22
|
+
when "include"
|
23
|
+
if val.respond_to?(:each)
|
24
|
+
val.each{ |arg| included.push(arg.to_s) }
|
25
|
+
else
|
26
|
+
included.push(val.to_s)
|
27
|
+
end
|
28
|
+
when "exclude"
|
29
|
+
if val.respond_to?(:each)
|
30
|
+
val.each{ |arg| excluded.push(arg.to_s) }
|
31
|
+
else
|
32
|
+
excluded.push(val.to_s)
|
33
|
+
end
|
34
|
+
when "alias"
|
35
|
+
aliased.push(val)
|
36
|
+
else
|
37
|
+
raise "invalid key '#{key}'"
|
66
38
|
end
|
67
|
-
|
68
|
-
|
69
|
-
if key.to_s == "alias"
|
70
|
-
aliased.push(val)
|
71
|
-
end
|
72
|
-
}
|
73
|
-
else
|
74
|
-
if methods.empty?
|
75
|
-
module_eval{ include mod } # Mixin all methods if no arguments
|
39
|
+
}
|
76
40
|
else
|
77
|
-
|
78
|
-
include mod
|
79
|
-
all_methods = mod.instance_methods
|
80
|
-
unn_methods = all_methods - methods.map{ |method| method.to_s }
|
81
|
-
undef_method(*unn_methods)
|
82
|
-
end
|
83
|
-
module_eval{ include m }
|
41
|
+
included.push(arg.to_s)
|
84
42
|
end
|
85
|
-
|
86
|
-
end
|
43
|
+
}
|
87
44
|
|
88
45
|
unless included.empty? || excluded.empty?
|
89
46
|
err = "you cannot include and exclude in the same statement"
|
90
47
|
raise ArgumentError, err
|
91
48
|
end
|
92
49
|
|
93
|
-
|
94
|
-
include mod
|
50
|
+
imethods = mod.instance_methods
|
95
51
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
undef_method(old) # Then remove the old method
|
101
|
-
}
|
52
|
+
# Remove excluded methods
|
53
|
+
unless excluded.empty?
|
54
|
+
(imethods & excluded).each{ |meth|
|
55
|
+
mod.module_eval{ remove_method(meth) }
|
102
56
|
}
|
57
|
+
end
|
103
58
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
59
|
+
# Alias methods
|
60
|
+
aliased.each{ |pair|
|
61
|
+
pair.each{ |old, new|
|
62
|
+
included.push(old) # Aliased methods automatically included
|
63
|
+
mod.module_eval{
|
64
|
+
alias_method(new, old)
|
65
|
+
remove_method(old)
|
111
66
|
}
|
112
|
-
end
|
113
|
-
|
114
|
-
# Undef all methods in the 'excluded' array
|
115
|
-
excluded.each{ |method|
|
116
|
-
undef_method(method) if method_defined?(method)
|
117
67
|
}
|
118
68
|
}
|
119
69
|
|
120
|
-
|
70
|
+
# Remove all methods not specifically included. The rescue was needed
|
71
|
+
# for those cases where a module included another module.
|
72
|
+
unless included.empty?
|
73
|
+
(imethods - included).each{ |meth|
|
74
|
+
mod.module_eval{ undef_method(meth) rescue nil }
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
m.module_eval{ include mod }
|
79
|
+
|
80
|
+
# Raise a warning if methods are shadowed (in $VERBOSE mode)
|
81
|
+
if $VERBOSE
|
82
|
+
imethods = instance_methods(true)
|
83
|
+
m.instance_methods.each{ |meth|
|
84
|
+
next unless imethods.include?(meth)
|
85
|
+
warn "method '#{meth}' aliased, shadows old '#{meth}'"
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
include m
|
121
90
|
end
|
122
91
|
end
|
data/test/tc_use.rb
CHANGED
@@ -1,115 +1,103 @@
|
|
1
|
-
|
1
|
+
#######################################################################
|
2
2
|
# tc_use.rb
|
3
3
|
#
|
4
|
-
# Test
|
5
|
-
|
4
|
+
# Test cases for the 'use' package. The relevant modules and classes
|
5
|
+
# are stored in the 'test_data.rb' file.
|
6
|
+
#######################################################################
|
6
7
|
base = File.basename(Dir.pwd)
|
7
|
-
|
8
|
-
if base ==
|
9
|
-
Dir.
|
10
|
-
|
11
|
-
$LOAD_PATH.unshift
|
12
|
-
Dir.chdir("test") rescue nil
|
13
|
-
end
|
14
|
-
|
15
|
-
require "use"
|
16
|
-
require "test/unit"
|
17
|
-
|
18
|
-
module Foo
|
19
|
-
def bar; self; end
|
20
|
-
def baz; "hello"; end
|
21
|
-
def zap; "world"; end
|
8
|
+
if base == 'test' || base =~ /use/i
|
9
|
+
Dir.chdir '..' if base == 'test'
|
10
|
+
$LOAD_PATH.unshift Dir.pwd + '/lib'
|
11
|
+
Dir.chdir 'test' rescue nil
|
12
|
+
$LOAD_PATH.unshift Dir.pwd
|
22
13
|
end
|
23
14
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
15
|
+
require 'use'
|
16
|
+
require 'test_data'
|
17
|
+
require 'test/unit'
|
28
18
|
|
29
|
-
class
|
30
|
-
|
31
|
-
|
19
|
+
class TC_Use < Test::Unit::TestCase
|
20
|
+
def setup
|
21
|
+
@a = ClassA.new
|
22
|
+
@b = ClassB.new
|
23
|
+
@c = ClassC.new
|
24
|
+
@d = ClassD.new
|
25
|
+
end
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
:alias => {:baz, :test}
|
37
|
-
end
|
27
|
+
def test_version
|
28
|
+
assert_equal('1.2.0', Class::USE_VERSION)
|
29
|
+
end
|
38
30
|
|
39
|
-
|
40
|
-
|
41
|
-
|
31
|
+
def test_mod_a_methods
|
32
|
+
assert_equal(['meth_a', 'meth_b', 'meth_c'], ModA.instance_methods.sort)
|
33
|
+
end
|
42
34
|
|
43
|
-
def
|
44
|
-
|
35
|
+
def test_mod_b_methods
|
36
|
+
assert_equal(['meth_a', 'meth_b', 'meth_c'], ModB.instance_methods.sort)
|
45
37
|
end
|
46
|
-
end
|
47
38
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
:exclude => :bar
|
52
|
-
end
|
39
|
+
def test_mod_c_methods
|
40
|
+
assert_equal(['meth_x', 'meth_y', 'meth_z'], ModC.instance_methods.sort)
|
41
|
+
end
|
53
42
|
|
54
|
-
|
55
|
-
|
56
|
-
@
|
57
|
-
@temp = Temp.new
|
58
|
-
@zapr = Zapr.new
|
43
|
+
def test_class_a_methods
|
44
|
+
assert_respond_to(@a, :meth_a)
|
45
|
+
assert_equal('ModA#meth_a', @a.meth_a)
|
59
46
|
end
|
60
47
|
|
61
|
-
def
|
62
|
-
|
48
|
+
def test_class_a_expected_errors
|
49
|
+
assert_raises(NoMethodError){ @a.meth_b }
|
50
|
+
assert_raises(NoMethodError){ @a.meth_c }
|
63
51
|
end
|
64
52
|
|
65
|
-
def
|
66
|
-
assert_respond_to(@
|
67
|
-
assert_respond_to(@
|
68
|
-
assert_equal(
|
53
|
+
def test_class_b_methods
|
54
|
+
assert_respond_to(@b, :meth_c)
|
55
|
+
assert_respond_to(@b, :meth_z)
|
56
|
+
assert_equal('ModA#meth_c', @b.meth_c)
|
57
|
+
assert_equal('ModB#meth_b', @b.meth_z)
|
69
58
|
end
|
70
59
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
assert_equal("world", @temp.zap)
|
75
|
-
assert_equal("hello", @temp.test)
|
60
|
+
def test_class_b_expected_errors
|
61
|
+
assert_raises(NoMethodError){ @b.meth_a }
|
62
|
+
assert_raises(NoMethodError){ @b.meth_b }
|
76
63
|
end
|
77
64
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
65
|
+
def test_class_c_methods
|
66
|
+
assert_respond_to(@c, :meth_a)
|
67
|
+
assert_respond_to(@c, :meth_c)
|
68
|
+
assert_respond_to(@c, :meth_x)
|
69
|
+
assert_respond_to(@c, :meth_y)
|
70
|
+
assert_respond_to(@c, :meth_z)
|
71
|
+
|
72
|
+
assert_equal('ModA#meth_a', @c.meth_a)
|
73
|
+
assert_equal('ClassC#meth_c', @c.meth_c)
|
74
|
+
assert_equal('ModC#meth_x', @c.meth_x)
|
75
|
+
assert_equal('ModC#meth_y', @c.meth_y)
|
76
|
+
assert_equal('ModC#meth_z', @c.meth_z)
|
81
77
|
end
|
82
|
-
|
83
|
-
def
|
84
|
-
|
85
|
-
assert_nothing_raised{ @user.bar }
|
86
|
-
assert_kind_of(User, @user.bar)
|
78
|
+
|
79
|
+
def test_class_c_expected_errors
|
80
|
+
assert_raises(NoMethodError){ @c.meth_b }
|
87
81
|
end
|
88
|
-
|
89
|
-
def
|
90
|
-
|
91
|
-
|
82
|
+
|
83
|
+
def test_class_d_methods
|
84
|
+
assert_respond_to(@d, :meth_x)
|
85
|
+
assert_respond_to(@d, :meth_z)
|
86
|
+
|
87
|
+
assert_equal('ModA#meth_a', @d.meth_x)
|
88
|
+
assert_equal('ModA#meth_c', @d.meth_z)
|
92
89
|
end
|
93
90
|
|
94
|
-
|
95
|
-
|
96
|
-
assert_raises(
|
97
|
-
|
98
|
-
"class Bogus
|
99
|
-
use Foo, :include => :bar, :exclude => :zap
|
100
|
-
end"
|
101
|
-
}
|
102
|
-
}
|
103
|
-
assert_raises(ArgumentError){
|
104
|
-
eval{
|
105
|
-
"class Bogus
|
106
|
-
use Foo, :alias => {:bar,:blah}, :exclude => :zap
|
107
|
-
end"
|
108
|
-
}
|
109
|
-
}
|
91
|
+
def test_class_d_expected_errors
|
92
|
+
assert_raises(NoMethodError){ @d.meth_a }
|
93
|
+
assert_raises(NoMethodError){ @d.meth_b }
|
94
|
+
assert_raises(NoMethodError){ @d.meth_c }
|
110
95
|
end
|
111
|
-
|
96
|
+
|
112
97
|
def teardown
|
113
|
-
@
|
98
|
+
@a = nil
|
99
|
+
@b = nil
|
100
|
+
@c = nil
|
101
|
+
@d = nil
|
114
102
|
end
|
115
103
|
end
|
data/test/test_data.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
##################################################
|
2
|
+
# test_data.rb
|
3
|
+
#
|
4
|
+
# Test modules and classes for the 'use' package.
|
5
|
+
##################################################
|
6
|
+
#if File.basename(Dir.pwd) == "test"
|
7
|
+
# Dir.chdir(".."){
|
8
|
+
# $LOAD_PATH.unshift(Dir.pwd)
|
9
|
+
# $LOAD_PATH.unshift(Dir.pwd + "/lib")
|
10
|
+
# }
|
11
|
+
#end
|
12
|
+
#$LOAD_PATH.unshift(Dir.pwd + "/lib")
|
13
|
+
|
14
|
+
module ModA
|
15
|
+
def meth_a
|
16
|
+
"ModA#meth_a"
|
17
|
+
end
|
18
|
+
|
19
|
+
def meth_b
|
20
|
+
"ModA#meth_b"
|
21
|
+
end
|
22
|
+
|
23
|
+
def meth_c
|
24
|
+
"ModA#meth_c"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module ModB
|
29
|
+
include ModA
|
30
|
+
def meth_a
|
31
|
+
"ModB#meth_a"
|
32
|
+
end
|
33
|
+
|
34
|
+
def meth_b
|
35
|
+
"ModB#meth_b"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module ModC
|
40
|
+
def meth_x
|
41
|
+
"ModC#meth_x"
|
42
|
+
end
|
43
|
+
|
44
|
+
def meth_y
|
45
|
+
"ModC#meth_y"
|
46
|
+
end
|
47
|
+
|
48
|
+
def meth_z
|
49
|
+
"ModC#meth_z"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class ClassA
|
54
|
+
use ModA, :meth_a
|
55
|
+
end
|
56
|
+
|
57
|
+
class ClassB
|
58
|
+
use ModB, :include => :meth_c, :alias => {:meth_b, :meth_z}
|
59
|
+
end
|
60
|
+
|
61
|
+
class ClassC
|
62
|
+
use ModA, :exclude => [:meth_b, :meth_c]
|
63
|
+
use ModC
|
64
|
+
|
65
|
+
def meth_c
|
66
|
+
"ClassC#meth_c"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class ClassD
|
71
|
+
use ModA, :alias => {:meth_a, :meth_x, :meth_c, :meth_z}, :exclude => :meth_b
|
72
|
+
end
|
metadata
CHANGED
@@ -3,11 +3,11 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: use
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date: 2006-
|
6
|
+
version: 1.2.0
|
7
|
+
date: 2006-02-24 00:00:00 -07:00
|
8
8
|
summary: Selectively mixin methods from a given module
|
9
9
|
require_paths:
|
10
|
-
|
10
|
+
- lib
|
11
11
|
email: djberg96@gmail.com
|
12
12
|
homepage: http://www.rubyforge.org/projects/shards
|
13
13
|
rubyforge_project:
|
@@ -18,29 +18,34 @@ bindir: bin
|
|
18
18
|
has_rdoc: true
|
19
19
|
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
20
|
requirements:
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
version: 0.0.0
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
25
24
|
version:
|
26
25
|
platform: ruby
|
27
26
|
signing_key:
|
28
27
|
cert_chain:
|
29
28
|
authors:
|
30
|
-
|
29
|
+
- Daniel J. Berger
|
31
30
|
files:
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
- lib/use.rb
|
32
|
+
- CHANGES
|
33
|
+
- MANIFEST
|
34
|
+
- README
|
35
|
+
- test/tc_use.rb
|
36
|
+
- test/test_data.rb
|
37
37
|
test_files:
|
38
|
-
|
38
|
+
- test/tc_use.rb
|
39
39
|
rdoc_options: []
|
40
|
+
|
40
41
|
extra_rdoc_files:
|
41
|
-
|
42
|
-
|
42
|
+
- README
|
43
|
+
- CHANGES
|
43
44
|
executables: []
|
45
|
+
|
44
46
|
extensions: []
|
47
|
+
|
45
48
|
requirements: []
|
46
|
-
|
49
|
+
|
50
|
+
dependencies: []
|
51
|
+
|