irregular_method 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +37 -27
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/irregular_method.gemspec +6 -4
- data/lib/irregular_method.rb +13 -6
- data/spec/irregular_method_spec.rb +9 -0
- data/spec/models/modular.rb +40 -0
- data/spec/spec_helper.rb +1 -0
- metadata +7 -5
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= irregular_method
|
2
2
|
|
3
|
-
|
3
|
+
Rather than having a bunch of lame logic in your method_missing method, define separated regular expression methods that are called when no normally defined method matches.
|
4
4
|
|
5
5
|
== Installation
|
6
6
|
|
@@ -17,53 +17,63 @@ The purpose of irregular_method is to allow methods with regular expression name
|
|
17
17
|
...
|
18
18
|
end
|
19
19
|
|
20
|
-
All reg_def methods are passed back the MatchData and the arguments passed to the call. For instance, let's say we have this class:
|
20
|
+
All reg_def methods are passed back the MatchData[http://ruby-doc.org/core/classes/MatchData.html] and the arguments passed to the call. For instance, let's say we have this class:
|
21
21
|
|
22
|
-
class
|
22
|
+
class Account
|
23
23
|
include ::Irregular::Method
|
24
|
+
|
25
|
+
VALID_USER_TYPES = %w(janitor secretary manager)
|
26
|
+
has_many :users
|
24
27
|
|
25
|
-
|
26
|
-
|
28
|
+
reg_def(/^(#{VALID_USER_TYPES.join('|')})$/) do |match, args|
|
29
|
+
self.user(match[1])
|
30
|
+
end
|
27
31
|
|
28
|
-
|
29
|
-
|
30
|
-
layers[self.index + (above_or_below == 'above' && 1 || above_or_below == 'below' && -1 || 0)]
|
32
|
+
def user(of_type)
|
33
|
+
self.users.select{|u| u.type == of_type.classify}.first
|
31
34
|
end
|
32
|
-
end
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
+
end
|
37
|
+
This is a simple example, but this allows you to access a specific kind of user directly, rather than passing the type or creating separate method declarations. So now you can do account.secretary and you'll get back a secretary object. Similarly, account.janitor will pass back the accounts janitor if it exists.
|
38
|
+
What's nice about this is you no longer need to write a bunch of separate methods or messy logic in your method_missing. Instead, write it as reg_def's and have a cleaner definition of your class. Let's take a look at one more example with functionality separated out into a module:
|
36
39
|
|
37
|
-
|
40
|
+
module Modular
|
38
41
|
include ::Irregular::Method
|
39
|
-
|
40
|
-
has_many :users
|
41
|
-
has_many :cars
|
42
42
|
|
43
|
-
reg_def
|
44
|
-
self.
|
43
|
+
reg_def(/^say_(.+)$/) do |match, args|
|
44
|
+
self.speak(match[1].humanize)
|
45
|
+
end
|
46
|
+
|
47
|
+
def speak(words)
|
48
|
+
"#{self.name} says: #{words}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Talker
|
53
|
+
include Modular
|
54
|
+
|
55
|
+
def initialize(name)
|
56
|
+
@name = name
|
45
57
|
end
|
46
58
|
|
47
|
-
def
|
48
|
-
|
59
|
+
def name
|
60
|
+
@name
|
49
61
|
end
|
50
62
|
end
|
51
63
|
|
52
|
-
|
53
|
-
e.users
|
54
|
-
=> [#<User id: 1, created_at: "2010-01-27 01:09:42", updated_at: "2010-01-27 01:09:42">, #<User id: 4, created_at: "2010-01-27 03:09:42", updated_at: "2010-01-27 03:09:42">]
|
64
|
+
The above code allows you to do this:
|
55
65
|
|
56
|
-
|
57
|
-
|
66
|
+
t = Talker.new('John')
|
67
|
+
t.say_hello => 'John says: hello'
|
58
68
|
|
59
|
-
You
|
69
|
+
You can pass in a single regular expression to the reg_def method, or you can pass an array of expressions. If you pass an array, make sure the order is from most specific to least specific.
|
60
70
|
|
61
71
|
---
|
62
72
|
|
63
73
|
== Important Things (not from Demetri Martin)
|
64
|
-
* irregular_method can be used
|
74
|
+
* irregular_method can be used in ANY ruby class or module.
|
65
75
|
|
66
|
-
* The reference to 'self' IS a reference to the instance of the class. Normally, it would be a reference to the class since it's being evaluated as a class method, but
|
76
|
+
* The reference to 'self' IS a reference to the instance of the class. Normally, it would be a reference to the class since it's being evaluated as a class method, but the actual call to the block is bound to 'self'. In any case, using self to reference the instance of the class you're working with is absolutely correct.
|
67
77
|
|
68
78
|
== Copyright
|
69
79
|
|
data/Rakefile
CHANGED
@@ -5,8 +5,8 @@ begin
|
|
5
5
|
require 'jeweler'
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "irregular_method"
|
8
|
-
gem.summary = "Method missing is messy. Fix it by defining regular expression methods."
|
9
|
-
gem.description = "
|
8
|
+
gem.summary = "Method missing logic is messy. Fix it by defining regular expression methods."
|
9
|
+
gem.description = "Rather than having a bunch of lame logic in your method_missing method, define separated regular expression methods that are called when no normally defined method matches."
|
10
10
|
gem.email = "mdnelson30@gmail.com"
|
11
11
|
gem.homepage = "http://github.com/mnelson/irregular_method"
|
12
12
|
gem.authors = ["Mike Nelson"]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/irregular_method.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{irregular_method}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Mike Nelson"]
|
12
|
-
s.date = %q{2010-03-
|
13
|
-
s.description = %q{
|
12
|
+
s.date = %q{2010-03-19}
|
13
|
+
s.description = %q{Rather than having a bunch of lame logic in your method_missing method, define separated regular expression methods that are called when no normally defined method matches.}
|
14
14
|
s.email = %q{mdnelson30@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
"lib/irregular_method.rb",
|
28
28
|
"spec/irregular_method_spec.rb",
|
29
29
|
"spec/models/method_missing.rb",
|
30
|
+
"spec/models/modular.rb",
|
30
31
|
"spec/models/plain_object.rb",
|
31
32
|
"spec/models/user.rb",
|
32
33
|
"spec/schema.rb",
|
@@ -37,10 +38,11 @@ Gem::Specification.new do |s|
|
|
37
38
|
s.rdoc_options = ["--charset=UTF-8"]
|
38
39
|
s.require_paths = ["lib"]
|
39
40
|
s.rubygems_version = %q{1.3.6}
|
40
|
-
s.summary = %q{Method missing is messy. Fix it by defining regular expression methods.}
|
41
|
+
s.summary = %q{Method missing logic is messy. Fix it by defining regular expression methods.}
|
41
42
|
s.test_files = [
|
42
43
|
"spec/irregular_method_spec.rb",
|
43
44
|
"spec/models/method_missing.rb",
|
45
|
+
"spec/models/modular.rb",
|
44
46
|
"spec/models/plain_object.rb",
|
45
47
|
"spec/models/user.rb",
|
46
48
|
"spec/schema.rb",
|
data/lib/irregular_method.rb
CHANGED
@@ -1,30 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
|
1
4
|
module Irregular
|
5
|
+
|
2
6
|
module Method
|
3
7
|
|
4
8
|
def self.included(base)
|
5
|
-
base.extend Irregular::Method::ClassMethods
|
6
|
-
|
9
|
+
base.send :extend, Irregular::Method::ClassMethods
|
7
10
|
end
|
8
|
-
|
11
|
+
|
9
12
|
module ClassMethods
|
10
13
|
|
14
|
+
|
11
15
|
def reg_def(regex, &block)
|
12
|
-
if(!self.
|
16
|
+
if(!self.include?(Irregular::Method::InstanceMethods))
|
13
17
|
send(:include, Irregular::Method::InstanceMethods)
|
14
18
|
send('irregular_methods=', [])
|
15
19
|
end
|
20
|
+
|
16
21
|
irregular_methods << [[regex].flatten.compact, block]
|
17
22
|
end
|
18
23
|
end
|
19
24
|
|
20
25
|
module InstanceMethods
|
26
|
+
|
21
27
|
def self.included(base)
|
28
|
+
|
22
29
|
base.class_eval do
|
23
|
-
cattr_accessor :irregular_methods
|
30
|
+
base.respond_to?(:cattr_accessor) && cattr_accessor(:irregular_methods) || mattr_accessor(:irregular_methods)
|
24
31
|
end
|
32
|
+
|
25
33
|
end
|
26
34
|
|
27
|
-
|
28
35
|
def method_missing(name, *args)
|
29
36
|
method_id = name.to_s
|
30
37
|
irregular_methods && irregular_methods.each do |context|
|
@@ -31,4 +31,13 @@ describe "IrregularMethod" do
|
|
31
31
|
|
32
32
|
end
|
33
33
|
|
34
|
+
|
35
|
+
it "should integrate with modules" do
|
36
|
+
t = Talker.new('Johnny')
|
37
|
+
t.say_hello.should eql("Johnny says: hello")
|
38
|
+
|
39
|
+
t = NestedTalker.new('Charles')
|
40
|
+
t.say_hello.should eql("Charles says: hello")
|
41
|
+
end
|
42
|
+
|
34
43
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Modular
|
2
|
+
include ::Irregular::Method
|
3
|
+
|
4
|
+
reg_def(/^say_(.+)$/) do |match, args|
|
5
|
+
self.speak(match[1])
|
6
|
+
end
|
7
|
+
|
8
|
+
def speak(words)
|
9
|
+
"#{self.name} says: #{words}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Talker
|
14
|
+
include Modular
|
15
|
+
|
16
|
+
def initialize(name)
|
17
|
+
@name = name
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
@name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module NestedModular
|
26
|
+
include Modular
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class NestedTalker
|
31
|
+
include NestedModular
|
32
|
+
|
33
|
+
def initialize(name)
|
34
|
+
@name = name
|
35
|
+
end
|
36
|
+
|
37
|
+
def name
|
38
|
+
@name
|
39
|
+
end
|
40
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -8,6 +8,7 @@ require 'spec/autorun'
|
|
8
8
|
require 'models/method_missing'
|
9
9
|
require 'models/user'
|
10
10
|
require 'models/plain_object'
|
11
|
+
require 'models/modular'
|
11
12
|
|
12
13
|
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/debug.log')
|
13
14
|
ActiveRecord::Base.configurations = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 3
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Mike Nelson
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-19 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -31,7 +31,7 @@ dependencies:
|
|
31
31
|
version: 1.2.9
|
32
32
|
type: :development
|
33
33
|
version_requirements: *id001
|
34
|
-
description:
|
34
|
+
description: Rather than having a bunch of lame logic in your method_missing method, define separated regular expression methods that are called when no normally defined method matches.
|
35
35
|
email: mdnelson30@gmail.com
|
36
36
|
executables: []
|
37
37
|
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- lib/irregular_method.rb
|
52
52
|
- spec/irregular_method_spec.rb
|
53
53
|
- spec/models/method_missing.rb
|
54
|
+
- spec/models/modular.rb
|
54
55
|
- spec/models/plain_object.rb
|
55
56
|
- spec/models/user.rb
|
56
57
|
- spec/schema.rb
|
@@ -85,10 +86,11 @@ rubyforge_project:
|
|
85
86
|
rubygems_version: 1.3.6
|
86
87
|
signing_key:
|
87
88
|
specification_version: 3
|
88
|
-
summary: Method missing is messy. Fix it by defining regular expression methods.
|
89
|
+
summary: Method missing logic is messy. Fix it by defining regular expression methods.
|
89
90
|
test_files:
|
90
91
|
- spec/irregular_method_spec.rb
|
91
92
|
- spec/models/method_missing.rb
|
93
|
+
- spec/models/modular.rb
|
92
94
|
- spec/models/plain_object.rb
|
93
95
|
- spec/models/user.rb
|
94
96
|
- spec/schema.rb
|