missingno 0.0.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/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