use 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/CHANGES +11 -2
  2. data/MANIFEST +2 -0
  3. data/README +76 -54
  4. data/lib/use.rb +122 -18
  5. data/test/tc_use.rb +115 -49
  6. metadata +5 -5
data/CHANGES CHANGED
@@ -1,2 +1,11 @@
1
- == 1-Aug-2005
2
- * Initial release
1
+ == 1.1.0 - 20-Jan-2006
2
+ * Using 'use' with no arguments is now the same as if you used 'include',
3
+ i.e. all methods are mixed in. Previously, this would not mixin any methods.
4
+ * Added finer control of mixed in methods by allowing the use of three keyword
5
+ arguments - 'include', 'exclude' and 'alias'. See the documentation for
6
+ more details.
7
+ * Added more inline documentation.
8
+ * More tests and examples.
9
+
10
+ == 1.0.0 - 1-Aug-2005
11
+ * Initial release
data/MANIFEST CHANGED
@@ -4,6 +4,8 @@ README
4
4
  install.rb
5
5
  use.gemspec
6
6
 
7
+ examples/example_use.rb
8
+
7
9
  lib/use.rb
8
10
 
9
11
  test/tc_use.rb
data/README CHANGED
@@ -1,54 +1,76 @@
1
- == Description
2
- The 'use' package allows you to selectively mixin methods from a given
3
- module.
4
-
5
- == Prerequisites
6
- Ruby 1.8.0 or later
7
-
8
- == Installation
9
- === Standard
10
- ruby test/tc_use.rb (optional)
11
- ruby install.rb
12
-
13
- === Gem install
14
- ruby test/tc_use.rb (optional)
15
- ruby use.gemspec
16
- gem install use.gem
17
-
18
- == Synopsis
19
- module Foo
20
- def bar
21
- "hello"
22
- end
23
- def baz
24
- "world"
25
- end
26
- end
27
-
28
- class Zap
29
- use Foo, :bar
30
- end
31
-
32
- z = Zap.new
33
-
34
- z.bar # "hello"
35
- z.baz # NoMethodError
36
-
37
- == Acknowledgements
38
- Thanks go to Ara Howard for providing the solution.
39
-
40
- == Known Bugs
41
- None that I'm aware of. If you find any, please log them on the project
42
- page at http://www.rubyforge.org/projects/shards.
43
-
44
- == License
45
- Ruby's
46
-
47
- == Copyright
48
- (C) 2005, Daniel J. Berger
49
- All Rights Reserved
50
-
51
- == Author
52
- Daniel J. Berger
53
- djberg96@yahoo.com
54
- IRC nickname: imperator/rubyhacker1
1
+ == Description
2
+ The 'use' package allows you to selectively mixin methods from a given
3
+ module.
4
+
5
+ == Prerequisites
6
+ Ruby 1.8.0 or later
7
+
8
+ == Installation
9
+ === Standard
10
+ ruby test/tc_use.rb (optional)
11
+ ruby install.rb
12
+
13
+ === Gem install
14
+ ruby test/tc_use.rb (optional)
15
+ ruby use.gemspec
16
+ gem install use.gem
17
+
18
+ == Synopsis
19
+ module Foo
20
+ def bar
21
+ "hello"
22
+ end
23
+ def baz
24
+ "world"
25
+ end
26
+ end
27
+
28
+ module Test
29
+ def bar
30
+ "goodbye"
31
+ end
32
+ def blah
33
+ "new york"
34
+ end
35
+ end
36
+
37
+ class Zap
38
+ use Foo, :bar
39
+ use Test, :blah
40
+ end
41
+
42
+ z = Zap.new
43
+
44
+ z.bar # "hello"
45
+ z.baz # NoMethodError
46
+ z.blah # "new york"
47
+
48
+ # Using the new keywords
49
+ class MyKlass
50
+ use Foo :alias => {:bar, :test}
51
+ end
52
+
53
+ m = MyKlass.new
54
+ m.test # "hello"
55
+ m.bar # NoMethodError
56
+
57
+ == Acknowledgements
58
+ Thanks go to Ara Howard for providing the original solution and to
59
+ Mauricio Fernandez, who's blog I plagiarized to get the spoonful style
60
+ mixins.
61
+
62
+ == Known Bugs
63
+ None that I'm aware of. If you find any, please log them on the project
64
+ page at http://www.rubyforge.org/projects/shards.
65
+
66
+ == License
67
+ Ruby's
68
+
69
+ == Copyright
70
+ (C) 2005-2006, Daniel J. Berger
71
+ All Rights Reserved
72
+
73
+ == Author
74
+ Daniel J. Berger
75
+ djberg96 at gmail dot com
76
+ IRC nickname: imperator/mok (freenode)
data/lib/use.rb CHANGED
@@ -1,18 +1,122 @@
1
- class Module
2
- # VERSION 1.0.0
3
-
4
- # use(module, methods)
5
- #
6
- # The 'use' directive allows you to selectively mixin +methods+ from the
7
- # given +module+. The +methods+ may be either strings or symbols.
8
- def use(mod, *methods)
9
- m = Module.new
10
- m.module_eval do
11
- include mod
12
- all_methods = mod.instance_methods
13
- unn_methods = all_methods - methods.map{ |method| method.to_s }
14
- unn_methods.each{ |method| undef_method(method) }
15
- end
16
- module_eval{ include m }
17
- end
18
- end
1
+ class Module
2
+ # VERSION = "1.1.0"
3
+
4
+ # :call-seq:
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 = []
38
+ excluded = []
39
+ aliased = []
40
+
41
+ m = Module.new
42
+
43
+ # If the first argument is a Hash, verify the keywords and push values
44
+ # onto the appropriate array for later processing.
45
+ #
46
+ if methods.first.kind_of?(Hash)
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
52
+
53
+ if key.to_s == "include"
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
60
+
61
+ if key.to_s == "exclude"
62
+ if val.respond_to?(:each)
63
+ val.each{ |arg| excluded.push(arg.to_sym) }
64
+ else
65
+ excluded.push(val.to_sym)
66
+ end
67
+ end
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
76
+ else
77
+ m.module_eval do
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 }
84
+ end
85
+ return
86
+ end
87
+
88
+ unless included.empty? || excluded.empty?
89
+ err = "you cannot include and exclude in the same statement"
90
+ raise ArgumentError, err
91
+ end
92
+
93
+ m.module_eval{
94
+ include mod
95
+
96
+ aliased.each{ |pair|
97
+ pair.each{ |old, new|
98
+ included.push(old) # Aliased methods automatically included
99
+ alias_method(new, old) # Alias the old method
100
+ undef_method(old) # Then remove the old method
101
+ }
102
+ }
103
+
104
+ # Undef all methods not in the 'included' array
105
+ unless included.empty?
106
+ mod.instance_methods.each{ |method|
107
+ method = method.to_sym
108
+ unless included.include?(method)
109
+ undef_method(method) if method_defined?(method)
110
+ end
111
+ }
112
+ end
113
+
114
+ # Undef all methods in the 'excluded' array
115
+ excluded.each{ |method|
116
+ undef_method(method) if method_defined?(method)
117
+ }
118
+ }
119
+
120
+ module_eval{ include m }
121
+ end
122
+ end
data/test/tc_use.rb CHANGED
@@ -1,49 +1,115 @@
1
- ###############################################
2
- # tc_use.rb
3
- #
4
- # Test suite for the "use" package.
5
- ###############################################
6
- base = File.basename(Dir.pwd)
7
-
8
- if base == "test" || base =~ /use/
9
- Dir.chdir("..") if base == "test"
10
- $LOAD_PATH.unshift(Dir.pwd)
11
- $LOAD_PATH.unshift(Dir.pwd + "/lib")
12
- Dir.chdir("test") rescue nil
13
- end
14
-
15
- require "test/unit"
16
- require "use"
17
-
18
- module Foo
19
- def bar; self; end
20
- def baz; self; end
21
- end
22
-
23
- class User
24
- use Foo, :bar
25
- end
26
-
27
- class TC_Use < Test::Unit::TestCase
28
- def setup
29
- @user = User.new
30
- end
31
-
32
- def test_mod_methods
33
- assert_equal(["baz","bar"], Foo.instance_methods)
34
- end
35
-
36
- def test_bar_legal
37
- assert_respond_to(@user, :bar)
38
- assert_nothing_raised{ @user.bar }
39
- assert_kind_of(User, @user.bar)
40
- end
41
-
42
- def test_baz_not_legal
43
- assert_raises(NoMethodError){ @user.baz }
44
- end
45
-
46
- def teardown
47
- @user = nil
48
- end
49
- end
1
+ ###############################################
2
+ # tc_use.rb
3
+ #
4
+ # Test suite for the "use" package.
5
+ ###############################################
6
+ base = File.basename(Dir.pwd)
7
+
8
+ if base == "test" || base =~ /use/
9
+ Dir.chdir("..") if base == "test"
10
+ $LOAD_PATH.unshift(Dir.pwd)
11
+ $LOAD_PATH.unshift(Dir.pwd + "/lib")
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
22
+ end
23
+
24
+ module Bar
25
+ def bar; "bar!"; end
26
+ def baz; "baz!"; end
27
+ end
28
+
29
+ class User
30
+ use Foo, :bar
31
+ end
32
+
33
+ class Temp
34
+ use Foo,
35
+ :include => :zap,
36
+ :alias => {:baz, :test}
37
+ end
38
+
39
+ class Zapr
40
+ use Foo, :exclude => [:bar, :baz]
41
+ use Bar
42
+
43
+ def zap
44
+ "zap"
45
+ end
46
+ end
47
+
48
+ class Bogus
49
+ use Foo,
50
+ :alias => {"zap", :test1, :baz, :test2},
51
+ :exclude => :bar
52
+ end
53
+
54
+ class TC_Use < Test::Unit::TestCase
55
+ def setup
56
+ @user = User.new
57
+ @temp = Temp.new
58
+ @zapr = Zapr.new
59
+ end
60
+
61
+ def test_user_mod_methods
62
+ assert_equal(["bar","baz","zap"], Foo.instance_methods.sort)
63
+ end
64
+
65
+ def test_zapr_legal_methods
66
+ assert_respond_to(@zapr, :zap)
67
+ assert_respond_to(@zapr, :bar)
68
+ assert_equal("zap", @zapr.zap) # Existing method not overridden
69
+ end
70
+
71
+ def test_temp_legal_methods
72
+ assert_respond_to(@temp, :zap)
73
+ assert_respond_to(@temp, :test)
74
+ assert_equal("world", @temp.zap)
75
+ assert_equal("hello", @temp.test)
76
+ end
77
+
78
+ def test_temp_expected_errors
79
+ assert_raises(NoMethodError){ @temp.bar }
80
+ assert_raises(NoMethodError){ @temp.baz } # Aliased
81
+ end
82
+
83
+ def test_user_legal_methods
84
+ assert_respond_to(@user, :bar)
85
+ assert_nothing_raised{ @user.bar }
86
+ assert_kind_of(User, @user.bar)
87
+ end
88
+
89
+ def test_user_expected_errors
90
+ assert_raises(NoMethodError){ @user.baz }
91
+ assert_raises(NoMethodError){ @user.zap }
92
+ end
93
+
94
+ # Don't allow exclude and include
95
+ def test_mutual_exclusion
96
+ assert_raises(ArgumentError){
97
+ eval{
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
+ }
110
+ end
111
+
112
+ def teardown
113
+ @user = nil
114
+ end
115
+ end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.6
2
+ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: use
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.0
7
- date: 2005-08-01
6
+ version: 1.1.0
7
+ date: 2006-01-20 00:00:00 -07:00
8
8
  summary: Selectively mixin methods from a given module
9
9
  require_paths:
10
10
  - lib
@@ -24,15 +24,15 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
24
24
  version: 0.0.0
25
25
  version:
26
26
  platform: ruby
27
+ signing_key:
28
+ cert_chain:
27
29
  authors:
28
30
  - Daniel J. Berger
29
31
  files:
30
32
  - lib/use.rb
31
33
  - CHANGES
32
- - CVS
33
34
  - MANIFEST
34
35
  - README
35
- - test/CVS
36
36
  - test/tc_use.rb
37
37
  test_files:
38
38
  - test/tc_use.rb