overridable 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.markdown +147 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/lib/overridable.rb +146 -0
- data/test/modulemixin_test.rb +48 -0
- data/test/overridable_test.rb +164 -0
- data/test/teststrap.rb +7 -0
- metadata +86 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 梁智敏
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
# Overridable
|
2
|
+
|
3
|
+
Overridable is a pure ruby library which helps you to make your methods which are defined in classes to be able to be overrided by mixed-in modules.
|
4
|
+
|
5
|
+
## Why?
|
6
|
+
|
7
|
+
We all know that it's impossible for modules to override methods that are defined in classes when they are included. For example:
|
8
|
+
class Thing
|
9
|
+
def foo
|
10
|
+
'Thing.foo'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Redef
|
15
|
+
def foo
|
16
|
+
'Redef.foo'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Thing.send :include, Redef
|
21
|
+
Thing.new.foo #=> Thing.foo # not Redef.foo
|
22
|
+
|
23
|
+
Usually, in order to achieve that goal, we will write the Redef module like this:
|
24
|
+
module Redef
|
25
|
+
def foo_with_redef
|
26
|
+
'Redef.foo'
|
27
|
+
end
|
28
|
+
# you can also do this by: alias_method_chain :foo, :redef, if you use ActiveSupport.
|
29
|
+
alias foo_without_redef foo
|
30
|
+
alias foo foo_with_redef
|
31
|
+
end
|
32
|
+
|
33
|
+
Thing.send :include, Redef
|
34
|
+
Thing.new.foo #=> Redef.foo
|
35
|
+
|
36
|
+
So it will likely become a with/without hell in your code ( you can find dozens of such methods in Rails' code ). And *overridable* is a library that provides a neat mean to resolve this problem.
|
37
|
+
|
38
|
+
## How?
|
39
|
+
|
40
|
+
There are two ways to do this with *overridable*: in class or in module.
|
41
|
+
|
42
|
+
### In class
|
43
|
+
|
44
|
+
Remember Thing and Redef in our first example? Let's make some changes:
|
45
|
+
require 'overridable'
|
46
|
+
|
47
|
+
Thing.class_eval {
|
48
|
+
include Overridable
|
49
|
+
overrides :foo
|
50
|
+
|
51
|
+
include Redef
|
52
|
+
}
|
53
|
+
|
54
|
+
Thing.new.foo #=> Redef.foo
|
55
|
+
That's it! You can specify which methods can be overrided by `overrides` method. One more example based on the previous one:
|
56
|
+
Thing.class_eval {
|
57
|
+
def bar; 'Thing.bar' end
|
58
|
+
def baz; 'Thing.baz' end
|
59
|
+
def id; 'Thing' end
|
60
|
+
|
61
|
+
overrides :bar, :baz
|
62
|
+
}
|
63
|
+
|
64
|
+
Redef.module_eval {
|
65
|
+
def bar; 'Redef.bar' end
|
66
|
+
def baz; 'Redef baz' end
|
67
|
+
def id; 'Redef' end
|
68
|
+
}
|
69
|
+
|
70
|
+
thing = Thing.new
|
71
|
+
thing.bar #=> 'Redef.bar'
|
72
|
+
thing.baz #=> 'Redef.baz'
|
73
|
+
thing.id #=> 'Thing'
|
74
|
+
Of course it's not the end of our story ;) How could I call this *override* if we cannot use `super`? Continue our example:
|
75
|
+
Redef.module_eval {
|
76
|
+
def bar
|
77
|
+
parent = super
|
78
|
+
me = 'Redef.bar'
|
79
|
+
"I'm #{me} and I overrided #{parent}"
|
80
|
+
end
|
81
|
+
}
|
82
|
+
|
83
|
+
Thing.new.bar => I'm Redef.bar and I overrided Thing.bar
|
84
|
+
|
85
|
+
### In module
|
86
|
+
|
87
|
+
If you have many methods in your module and find that it's too annoying to use `overrides`, then you can mix Overridable::ModuleMixin in your module. Example ( we all like examples, don't we? ):
|
88
|
+
class Thing
|
89
|
+
def method_one; ... end
|
90
|
+
def method_two; ... end
|
91
|
+
...
|
92
|
+
def method_n; ... end
|
93
|
+
end
|
94
|
+
|
95
|
+
module Redef
|
96
|
+
include Overridable::ModuleMixin
|
97
|
+
|
98
|
+
def method_one; ... end
|
99
|
+
def method_two; ... end
|
100
|
+
...
|
101
|
+
def method_n; ... end
|
102
|
+
end
|
103
|
+
|
104
|
+
Thing.send :include, Redef #=> method_one, method_two, ..., method_n are all overrided.
|
105
|
+
|
106
|
+
## Install
|
107
|
+
|
108
|
+
gem source -a http://gemcutter.org # you neednot do this if you have already had gemcutter in your source list
|
109
|
+
gem install overridable
|
110
|
+
|
111
|
+
## Dependencies
|
112
|
+
|
113
|
+
* Ruby >= 1.8.7
|
114
|
+
* riot >= 0.10.0 just for test
|
115
|
+
* yard >= 0.4.0 just for generating document
|
116
|
+
|
117
|
+
## Test
|
118
|
+
|
119
|
+
$> cd $GEM_HOME/gems/overridable-x.y.z
|
120
|
+
$> rake test # requires riot
|
121
|
+
|
122
|
+
## TODO
|
123
|
+
|
124
|
+
These features **only** will be added when they are asked for.
|
125
|
+
|
126
|
+
* :all and :except for overrides
|
127
|
+
overrides :all, :except => [:whatever, :excepts]
|
128
|
+
* override with block
|
129
|
+
override :foo do |*args|
|
130
|
+
super # or not
|
131
|
+
# any other stuff
|
132
|
+
end
|
133
|
+
* tell me what's missing.
|
134
|
+
|
135
|
+
## Note on Patches/Pull Requests
|
136
|
+
|
137
|
+
* Fork the project.
|
138
|
+
* Make your feature addition or bug fix.
|
139
|
+
* Add tests for it. This is important so I don't break it in a
|
140
|
+
future version unintentionally.
|
141
|
+
* Commit, do not mess with rakefile, version, or history.
|
142
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
143
|
+
* Send me a pull request. Bonus points for topic branches.
|
144
|
+
|
145
|
+
## Copyright
|
146
|
+
|
147
|
+
Copyright (c) 2009 梁智敏. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#--*-- encoding: UTF-8 --*--
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = "overridable"
|
9
|
+
gem.summary = %Q{Override methods without method alias.}
|
10
|
+
gem.description = %Q{Overridable is a pure ruby library which helps you to make your methods which are defined in classes to be able to be overrided by mixed-in modules.}
|
11
|
+
gem.email = "liang.gimi@gmail.com"
|
12
|
+
gem.homepage = "http://github.com/Gimi/overridable"
|
13
|
+
gem.authors = ["梁智敏(Gimi Liang)"]
|
14
|
+
gem.add_development_dependency "riot", ">= 0.10.0"
|
15
|
+
gem.add_development_dependency "yard", ">= 0.4.0"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rake/testtask'
|
24
|
+
Rake::TestTask.new(:test) do |test|
|
25
|
+
test.libs << 'lib' << 'test'
|
26
|
+
test.pattern = 'test/**/*_test.rb'
|
27
|
+
test.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
require 'rcov/rcovtask'
|
32
|
+
Rcov::RcovTask.new do |test|
|
33
|
+
test.libs << 'test'
|
34
|
+
test.pattern = 'test/**/*_test.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
task :rcov do
|
39
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
task :test => :check_dependencies
|
44
|
+
|
45
|
+
task :default => :test
|
46
|
+
|
47
|
+
begin
|
48
|
+
require 'yard'
|
49
|
+
YARD::Rake::YardocTask.new
|
50
|
+
rescue LoadError
|
51
|
+
task :yardoc do
|
52
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
53
|
+
end
|
54
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.0
|
data/lib/overridable.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
# Including this module in your class will give your class the ability to make its methods to be overridable by included modules. Let's look at some examples for easier understanding.
|
2
|
+
# @example
|
3
|
+
# class Thing
|
4
|
+
# def foo
|
5
|
+
# puts 'Thing.foo'
|
6
|
+
# end
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# module Foo
|
10
|
+
# def foo
|
11
|
+
# puts 'Foo.foo'
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# # If you don't use Overridable, you will get:
|
16
|
+
# Thing.send :include, Foo
|
17
|
+
# Thing.new.foo #=> print: Thing.foo\n
|
18
|
+
#
|
19
|
+
# # If you use Overridable *before* you include the module, things will become to be:
|
20
|
+
# Thing.class_eval {
|
21
|
+
# include Overridable
|
22
|
+
# overrides :foo # specifies which methods can be overrided.
|
23
|
+
# include Foo
|
24
|
+
# }
|
25
|
+
# Thing.new.foo => print: Foo.foo\n
|
26
|
+
#
|
27
|
+
# You are not just limited to write a brandnew method, but also call the original method by `super`.
|
28
|
+
# @example
|
29
|
+
# # Let's change the Foo module in the previous example:
|
30
|
+
# module Foo
|
31
|
+
# def foo
|
32
|
+
# super
|
33
|
+
# puts 'Foo.foo'
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# Thing.new.foo #=> print: Thing.foo\nFoo.foo\n
|
38
|
+
#
|
39
|
+
# Thanks to this feature, you don't need method chains any more! ;)
|
40
|
+
#
|
41
|
+
# You can also use Overridable::ModuleMixin to make things even a bit easier for some situations. See Overridable::ModuleMixin for details.
|
42
|
+
module Overridable
|
43
|
+
|
44
|
+
# If your module includes this module, then classes which include your module
|
45
|
+
# will make their methods which also defined in your module overridable.
|
46
|
+
# Let's watch an example:
|
47
|
+
# @example
|
48
|
+
# module YourModule
|
49
|
+
# include Overridable::ModuleMixin
|
50
|
+
#
|
51
|
+
# def foo
|
52
|
+
# super
|
53
|
+
# puts "foo in your module"
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# class YourClass
|
58
|
+
# def foo
|
59
|
+
# puts "foo in your class"
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# YourClass.new.foo #=> print: foo in your class\n
|
64
|
+
#
|
65
|
+
# YourClass.send :include, YourModule
|
66
|
+
#
|
67
|
+
# YourClass.new.foo #=> print: foo in your class\nfoo in your module\n
|
68
|
+
#
|
69
|
+
# __NOTE__: If you need a custom `append_features` method in your module,
|
70
|
+
# define that method before include this module in yours, or this is not
|
71
|
+
# going to work.
|
72
|
+
# @example
|
73
|
+
# module YourModule
|
74
|
+
# def self.append_features mod
|
75
|
+
# # things ...
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# include Overridable::ModuleMixin
|
79
|
+
# end
|
80
|
+
module ModuleMixin
|
81
|
+
def self.append_features mod #:nodoc:
|
82
|
+
class << mod
|
83
|
+
include Overridable
|
84
|
+
overrides :append_features
|
85
|
+
include ClassMethods
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
module ClassMethods
|
90
|
+
def append_features mod #:nodoc:
|
91
|
+
# these must be done in `append_features`, not `included`
|
92
|
+
mod.send :include, Overridable
|
93
|
+
mod.overrides *(
|
94
|
+
public_instance_methods +
|
95
|
+
protected_instance_methods +
|
96
|
+
private_instance_methods
|
97
|
+
)
|
98
|
+
super
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.included mod #:nodoc:
|
104
|
+
mod.extend ClassMethods
|
105
|
+
end
|
106
|
+
|
107
|
+
module ClassMethods #:nodoc:
|
108
|
+
# Specifies which methods can be overrided.
|
109
|
+
# @param [Symbol,String] method_names specifies one or more methods which can be overrided.
|
110
|
+
# @return nil
|
111
|
+
def overrides *method_names
|
112
|
+
return unless self.is_a?(Class) # do nothing if it's a module
|
113
|
+
methods =
|
114
|
+
method_names.map { |m| instance_method m rescue nil } \
|
115
|
+
.compact \
|
116
|
+
.select { |m| m.owner == self }
|
117
|
+
unless methods.empty?
|
118
|
+
# All overrided methods are defined in the same module
|
119
|
+
is_module_defined =
|
120
|
+
if method(:const_defined?).arity > 0 # 1.8.x
|
121
|
+
self.const_defined?(:OverridedMethods)
|
122
|
+
else # 1.9
|
123
|
+
self.const_defined?(:OverridedMethods, false)
|
124
|
+
end
|
125
|
+
|
126
|
+
unless is_module_defined
|
127
|
+
self.const_set(:OverridedMethods, Module.new)
|
128
|
+
include self.const_get(:OverridedMethods)
|
129
|
+
end
|
130
|
+
mod = const_get(:OverridedMethods)
|
131
|
+
|
132
|
+
old_verbose, $VERBOSE = $VERBOSE, nil # supress warnings
|
133
|
+
methods.each { |m|
|
134
|
+
remove_method m.name
|
135
|
+
mod.send :define_method, m.name do |*args, &blk|
|
136
|
+
m.bind(self).call(*args, &blk)
|
137
|
+
end
|
138
|
+
}
|
139
|
+
$VERBOSE = old_verbose
|
140
|
+
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'teststrap'
|
2
|
+
|
3
|
+
context "A module which includes Overridable::ModuleMixin has some methods defined in it." do
|
4
|
+
setup {
|
5
|
+
module SomeModule
|
6
|
+
include Overridable::ModuleMixin
|
7
|
+
|
8
|
+
def foo
|
9
|
+
'SomeModule.foo'
|
10
|
+
end
|
11
|
+
|
12
|
+
def bar a
|
13
|
+
super + 'SomeModule.bar'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
SomeModule
|
18
|
+
}
|
19
|
+
|
20
|
+
context "A class which has the same methods that are defined in that module," do
|
21
|
+
setup {
|
22
|
+
class SomeClass
|
23
|
+
def foo
|
24
|
+
'SomeClass.foo'
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def bar a
|
29
|
+
'SomeClass.bar'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
SomeClass
|
34
|
+
}
|
35
|
+
|
36
|
+
context "includes that module." do
|
37
|
+
setup { topic.send :include, SomeModule; topic }
|
38
|
+
|
39
|
+
asserts("foo should be overrided.") {
|
40
|
+
topic.new.foo
|
41
|
+
}.equals('SomeModule.foo')
|
42
|
+
asserts("bar should be overrided.") {
|
43
|
+
#topic.new.send :bar, :whatever
|
44
|
+
topic.new.bar :whatever
|
45
|
+
}.equals('SomeClass.bar' + 'SomeModule.bar')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'teststrap'
|
2
|
+
|
3
|
+
context "a classes with some methods defined in it" do
|
4
|
+
setup {
|
5
|
+
class Thing
|
6
|
+
def no_arguments
|
7
|
+
'This is Thing.'
|
8
|
+
end
|
9
|
+
|
10
|
+
def one_argument a
|
11
|
+
a
|
12
|
+
end
|
13
|
+
|
14
|
+
def any_arguments *args
|
15
|
+
args.join('-')
|
16
|
+
end
|
17
|
+
|
18
|
+
def with_block *args, &blk
|
19
|
+
blk.call(*args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def keep_unchanged
|
23
|
+
'unchanged'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Thing
|
28
|
+
}
|
29
|
+
|
30
|
+
context "includes a module which has the sames methods" do
|
31
|
+
setup {
|
32
|
+
module ModuleA
|
33
|
+
def no_arguments
|
34
|
+
'This is ModuleA.'
|
35
|
+
end
|
36
|
+
|
37
|
+
def one_argument a
|
38
|
+
a * 10
|
39
|
+
end
|
40
|
+
|
41
|
+
def any_arguments *args
|
42
|
+
args.join('_')
|
43
|
+
end
|
44
|
+
|
45
|
+
def with_block *args, &blk
|
46
|
+
blk.call(*args.map! { |a| a * 10 })
|
47
|
+
end
|
48
|
+
|
49
|
+
def keep_unchanged
|
50
|
+
'changed'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
topic.send :include, ModuleA
|
55
|
+
topic
|
56
|
+
}
|
57
|
+
|
58
|
+
# If these tests fail, that means we don't need this library any more ;)
|
59
|
+
asserts("no_arguments should not be overrided") { topic.new.no_arguments } \
|
60
|
+
.equals('This is Thing.')
|
61
|
+
asserts("one_argument should not be overrided") { topic.new.one_argument(10) } \
|
62
|
+
.equals(10)
|
63
|
+
asserts("any_arguments should not be overrided") { topic.new.any_arguments('a', 'b', 'c') } \
|
64
|
+
.equals(%w[a b c].join('-'))
|
65
|
+
asserts("with_block should not be overrided") { topic.new.with_block('a', 'b', 'c') { |*args| args.join('-') } } \
|
66
|
+
.equals(%w[a b c].join('-'))
|
67
|
+
asserts("keep_unchanged should not be overrided") { topic.new.keep_unchanged } \
|
68
|
+
.equals('unchanged')
|
69
|
+
end
|
70
|
+
|
71
|
+
context "includes Overridable and specifies methods to be overrided," do
|
72
|
+
setup {
|
73
|
+
topic.class_eval {
|
74
|
+
include Overridable
|
75
|
+
overrides :no_arguments, :one_argument, :any_arguments, :with_block
|
76
|
+
}
|
77
|
+
|
78
|
+
topic
|
79
|
+
}
|
80
|
+
|
81
|
+
context "then includes a module which has the same methods" do
|
82
|
+
setup {
|
83
|
+
module ModuleB
|
84
|
+
def no_arguments
|
85
|
+
'This is ModuleB.'
|
86
|
+
end
|
87
|
+
|
88
|
+
def one_argument a
|
89
|
+
a * 10
|
90
|
+
end
|
91
|
+
|
92
|
+
def any_arguments *args
|
93
|
+
args.join('_')
|
94
|
+
end
|
95
|
+
|
96
|
+
def with_block *args, &blk
|
97
|
+
blk.call(*args.map! { |a| a * 10 })
|
98
|
+
end
|
99
|
+
|
100
|
+
def keep_unchanged
|
101
|
+
'changed'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
topic.send :include, ModuleB
|
106
|
+
topic
|
107
|
+
}
|
108
|
+
|
109
|
+
asserts("no_arguments have been overrided") { topic.new.no_arguments } \
|
110
|
+
.equals('This is ModuleB.')
|
111
|
+
asserts("one_argument have been overrided") { topic.new.one_argument(10) } \
|
112
|
+
.equals(10 * 10)
|
113
|
+
asserts("any_arguments have been overrided") { topic.new.any_arguments('a', 'b', 'c') } \
|
114
|
+
.equals(%w[a b c].join('_'))
|
115
|
+
asserts("with_block have been overrided") { topic.new.with_block('a', 'b', 'c') { |*args| args.join('-') } } \
|
116
|
+
.equals(%w[a b c].map! { |e| e * 10 }.join('-'))
|
117
|
+
asserts("keep_unchanged should not be overrided") { topic.new.keep_unchanged } \
|
118
|
+
.equals('unchanged')
|
119
|
+
end
|
120
|
+
|
121
|
+
context "then includes a module with the same methods which call super in their bodies." do
|
122
|
+
setup {
|
123
|
+
module ModuleC
|
124
|
+
def no_arguments
|
125
|
+
super +
|
126
|
+
'This is ModuleC.'
|
127
|
+
end
|
128
|
+
|
129
|
+
def one_argument a
|
130
|
+
super + 123
|
131
|
+
end
|
132
|
+
|
133
|
+
def any_arguments *args
|
134
|
+
[super, args.join('_')].join('@')
|
135
|
+
end
|
136
|
+
|
137
|
+
def with_block *args, &blk
|
138
|
+
super(*args.map! { |e| "|#{e}|" }, &blk)
|
139
|
+
end
|
140
|
+
|
141
|
+
def keep_unchanged
|
142
|
+
super
|
143
|
+
'changed'
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
topic.send :include, ModuleC
|
148
|
+
topic
|
149
|
+
}
|
150
|
+
|
151
|
+
asserts("no_arguments have been overrided and work properly.") { topic.new.no_arguments } \
|
152
|
+
.equals('This is Thing.' + 'This is ModuleC.')
|
153
|
+
asserts("one_argument have been overrided and work properly.") { topic.new.one_argument(10) } \
|
154
|
+
.equals(10 + 123)
|
155
|
+
asserts("any_arguments have been overrided and work properly.") { topic.new.any_arguments('a', 'b', 'c') } \
|
156
|
+
.equals([%w[a b c].join('-'), %w[a b c].join('_')].join('@'))
|
157
|
+
asserts("with_block have been overrided and work properly.") { topic.new.with_block('a', 'b', 'c') { |*args| args.join('-') } } \
|
158
|
+
.equals(%w[a b c].map! { |e| "|#{e}|" }.join('-'))
|
159
|
+
asserts("keep_unchanged should not be overrided") { topic.new.keep_unchanged } \
|
160
|
+
.equals('unchanged')
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
data/test/teststrap.rb
ADDED
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: overridable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "\xE6\xA2\x81\xE6\x99\xBA\xE6\x95\x8F(Gimi Liang)"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-24 00:00:00 +08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: riot
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.10.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: yard
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.4.0
|
34
|
+
version:
|
35
|
+
description: Overridable is a pure ruby library which helps you to make your methods which are defined in classes to be able to be overrided by mixed-in modules.
|
36
|
+
email: liang.gimi@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README.markdown
|
44
|
+
files:
|
45
|
+
- .document
|
46
|
+
- .gitignore
|
47
|
+
- LICENSE
|
48
|
+
- README.markdown
|
49
|
+
- Rakefile
|
50
|
+
- VERSION
|
51
|
+
- lib/overridable.rb
|
52
|
+
- test/modulemixin_test.rb
|
53
|
+
- test/overridable_test.rb
|
54
|
+
- test/teststrap.rb
|
55
|
+
has_rdoc: true
|
56
|
+
homepage: http://github.com/Gimi/overridable
|
57
|
+
licenses: []
|
58
|
+
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options:
|
61
|
+
- --charset=UTF-8
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: "0"
|
75
|
+
version:
|
76
|
+
requirements: []
|
77
|
+
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 1.3.5
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: Override methods without method alias.
|
83
|
+
test_files:
|
84
|
+
- test/overridable_test.rb
|
85
|
+
- test/modulemixin_test.rb
|
86
|
+
- test/teststrap.rb
|