use 1.0.0 → 1.1.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.
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