missingno 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2009 Tobias Cohen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,26 @@
1
+ = Missingno - automated method_missing generator
2
+
3
+ Automated <tt>method_missing</tt> and <tt>respond_to?</tt> generator.
4
+
5
+ == Features
6
+
7
+ * Add convenience methods for your classes defined by a regular expression, or by any other construct that responds to <tt>===</tt> or <tt>include?</tt>
8
+ * Create both <tt>method_missing</tt> and <tt>respond_to?</tt> methods without repeating yourself
9
+ * Add convenience methods even when extending classes that already have <tt>method_missing</tt> defined.
10
+ * Add convenience methods to Mixins
11
+
12
+ == Example
13
+
14
+ require 'missingno'
15
+
16
+ class Model
17
+ def find(field, value)
18
+ #do stuff
19
+ end
20
+ def_when /^find_by_(.+)$/, :find
21
+ #i.e. find_by_state 'VIC'
22
+
23
+ def_when ['update', 'refresh', 'load'] do
24
+ #do stuff
25
+ end
26
+ end
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'spec/rake/spectask'
2
+ Spec::Rake::SpecTask.new
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |s|
7
+ s.name = "missingno"
8
+ s.summary = "automated method_missing generator"
9
+ s.email = "me@tobiascohen.com"
10
+ s.homepage = "http://github.com/tobico/missingno"
11
+ s.description = "Automated method_missing and respond_to? generator"
12
+ s.authors = ["Tobias Cohen"]
13
+ end
14
+ Jeweler::GemcutterTasks.new
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
17
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
data/lib/missingno.rb ADDED
@@ -0,0 +1,81 @@
1
+ class Module
2
+
3
+ # Define a method_missing handler that matches given object.
4
+ #
5
+ # Specify either a block to call, or a second argument containing
6
+ # a symbol with the name of method to call.
7
+ #
8
+ # If the match object is a regular expression that contains sub-matches,
9
+ # these matches will be passed to the callback before any passed arguments.
10
+ #
11
+ # Blocks passed to this method may not themselves take a block argument
12
+ # or yield to a block.
13
+
14
+ def def_when object, *args, &method
15
+ missingno_init
16
+ @missingno_chain << [object, !method.nil? ? method : args[0]]
17
+ end
18
+
19
+ private
20
+
21
+ # Get the specified method as an UnboundMethod object, or nil if none
22
+ # exists
23
+
24
+ def missingno_get_old_method method_name
25
+ if method_defined? method_name
26
+ instance_method method_name
27
+ else
28
+ nil
29
+ end
30
+ end
31
+
32
+ # Initialize the missingno chain and override method_missing and respond_to?
33
+ # methods for class.
34
+
35
+ def missingno_init
36
+ return if defined? @missingno_chain
37
+
38
+ chain = @missingno_chain = []
39
+ is_a_class = is_a? Class
40
+
41
+ old_method_missing = missingno_get_old_method :method_missing
42
+ define_method :method_missing do |sym, *args, &block|
43
+ item = chain.find do |item|
44
+ if item[0].respond_to? :include?
45
+ item[0].include? sym.to_s
46
+ else
47
+ item[0] === sym.to_s
48
+ end
49
+ end
50
+ if item
51
+ a = if item[0].is_a? Regexp
52
+ $~.to_a.slice(1..-1) + args
53
+ else
54
+ args
55
+ end
56
+ if item[1].is_a? Symbol
57
+ if m = method(item[1])
58
+ m.call *a, &block
59
+ end
60
+ else
61
+ instance_exec *a, &item[1]
62
+ end
63
+ elsif old_method_missing
64
+ old_method_missing.bind(self).call(sym, *args, &block)
65
+ elsif is_a_class
66
+ super
67
+ end
68
+ end
69
+
70
+ old_respond_to = missingno_get_old_method :respond_to?
71
+ define_method :respond_to? do |sym, *args|
72
+ if chain.any? { |item| item[0] === sym.to_s }
73
+ true
74
+ elsif old_respond_to
75
+ old_respond_to.bind(self).call(sym, *args)
76
+ elsif is_a_class
77
+ super
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,119 @@
1
+ require 'missingno'
2
+ require 'spec'
3
+
4
+ #Single class using missingno
5
+ class SingleClass
6
+ def_when /^(foo|bar)$/, :test
7
+ def_when ['one', 'two', 'three'] do
8
+ @ok = true
9
+ end
10
+ attr_accessor :ok
11
+ end
12
+
13
+ #Subclass of class using missingno
14
+ class SubClass < SingleClass
15
+ def_when /^zap$/, :sub_test
16
+ end
17
+
18
+ #Class with method_missing defined
19
+ class MMClass
20
+ def method_missing *args
21
+ "mmclass method_missing"
22
+ end
23
+
24
+ def_when 'foo', :missingno
25
+ end
26
+
27
+ #Subclass of class with method_missing defined
28
+ class MMSubClass < MMClass
29
+ def_when /^zap$/, :sub_test
30
+ end
31
+
32
+ #Mixin module using missingno
33
+ module MixinMM
34
+ def_when 'zap', :mm_zap
35
+ end
36
+
37
+ #Class using missingno with mixin
38
+ class MixedChain
39
+ include MixinMM
40
+ def_when 'foo', :mm_foo
41
+ end
42
+
43
+ describe 'missingno' do
44
+ describe 'with a single class' do
45
+ subject { SingleClass.new }
46
+
47
+ it 'should respond to symbols matching given regexp' do
48
+ should respond_to(:foo)
49
+ should respond_to(:bar)
50
+ should_not respond_to(:zap)
51
+ end
52
+
53
+ it 'should call nominated method when I call a matching (missing) method' do
54
+ subject.should_receive(:test)
55
+ subject.foo
56
+ end
57
+
58
+ it 'should receive the submatch as an argument to #test' do
59
+ subject.should_receive(:test).with('foo')
60
+ subject.foo
61
+ end
62
+
63
+ it 'should run specified block when matching array element given' do
64
+ subject.ok = false
65
+ subject.one
66
+ subject.ok.should == true
67
+ subject.ok = false
68
+ subject.three
69
+ subject.ok.should == true
70
+ end
71
+ end
72
+
73
+ describe 'with a subclass of a class also using missingno' do
74
+ subject { SubClass.new }
75
+
76
+ it 'should respond to matches from superclass' do
77
+ should respond_to(:foo)
78
+ should respond_to(:bar)
79
+ end
80
+
81
+ it 'should respond to matches from subclass' do
82
+ should respond_to(:zap)
83
+ end
84
+
85
+ it 'should call the correct methods when a match found' do
86
+ subject.should_receive :test
87
+ subject.foo
88
+ subject.should_receive :sub_test
89
+ subject.zap
90
+ end
91
+ end
92
+
93
+ describe 'with a class that already has method_missing' do
94
+ subject { MMClass.new }
95
+
96
+ it 'should call missingno method when I call a matching method' do
97
+ subject.should_receive :missingno
98
+ subject.foo
99
+ end
100
+
101
+ it 'should call original method_missing when I call a non-matching method' do
102
+ subject.zap.should == "mmclass method_missing"
103
+ end
104
+ end
105
+
106
+ describe 'through a mixin' do
107
+ subject { MixedChain.new }
108
+
109
+ it 'should call method matched in class' do
110
+ subject.should_receive :mm_foo
111
+ subject.foo
112
+ end
113
+
114
+ it 'should call method matched in mixin' do
115
+ subject.should_receive :mm_zap
116
+ subject.zap
117
+ end
118
+ end
119
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: missingno
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tobias Cohen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-10 00:00:00 +11:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Automated method_missing and respond_to? generator
17
+ email: me@tobiascohen.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - LICENSE
27
+ - README.rdoc
28
+ - Rakefile
29
+ - VERSION
30
+ - lib/missingno.rb
31
+ - spec/missingno_spec.rb
32
+ has_rdoc: true
33
+ homepage: http://github.com/tobico/missingno
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --charset=UTF-8
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project:
56
+ rubygems_version: 1.3.5
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: automated method_missing generator
60
+ test_files:
61
+ - spec/missingno_spec.rb