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.
@@ -1,6 +1,6 @@
1
1
  = irregular_method
2
2
 
3
- Writing a bunch of case statements to handle regular expressions in method missing is just plain annoying. I suggest they get separated out and defined as their own methods. Well... ruby doesn't really let that happen, but there is an alternative.
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 Layer
22
+ class Account
23
23
  include ::Irregular::Method
24
+
25
+ VALID_USER_TYPES = %w(janitor secretary manager)
26
+ has_many :users
24
27
 
25
- cattr_accessor :layers
26
- attr_accessible :index
28
+ reg_def(/^(#{VALID_USER_TYPES.join('|')})$/) do |match, args|
29
+ self.user(match[1])
30
+ end
27
31
 
28
- reg_def(/^layer_(.+)$/) do |m, args|
29
- above_or_below = m[1].downcase #first match in the expression
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
- What this is doing is matching a method looking like "layer_XXX". If the match (XXX) is 'above', than it's giving back the layer above the current one. If it's 'below' than it's giving back the layer below.
35
- What's nice about this is you no longer need to write a bunch of messy code 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:
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
- class Example < ActiveRecord::Base
40
+ module Modular
38
41
  include ::Irregular::Method
39
-
40
- has_many :users
41
- has_many :cars
42
42
 
43
- reg_def [/^capable_(.+)s$/, /^capable_(.+)$/] do |match, args|
44
- self.send["#{m[1]}s"].select{|item| self.capable?(item)}
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 capable?(something)
48
- ... # do something to determine if this object is "capable"
59
+ def name
60
+ @name
49
61
  end
50
62
  end
51
63
 
52
- e = Example.find 1
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
- e.capable_users
57
- => [#<User id: 1, created_at: "2010-01-27 01:09:42", updated_at: "2010-01-27 01:09:42">]
66
+ t = Talker.new('John')
67
+ t.say_hello => 'John says: hello'
58
68
 
59
- You may have noticed that you can pass an array to to the reg_def. It will check each element of that array for a match. ORDER IS IMPORTANT! Take the example case... If we swapped the order of the regular expressions we would be sending self the method "userss" which would obviously be incorrect. Now, please don't yell at me... I understand I should be using m[1].pluralize.... It's an EXAMPLE... and I didn't want to think too hard. It hurts when I do that.
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 on ANY ruby object.
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 there's a workaround. In any case, using self to reference the instance of the class you're working with is absolutely correct.
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 = "Writing a bunch of case statements to handle regular expressions in method missing is just plain annoying. I suggest they get separated out and defined as their own methods. Well... ruby doesn't really let that happen, so this is the alternative."
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.2.0
1
+ 0.3.0
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{irregular_method}
8
- s.version = "0.2.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-15}
13
- s.description = %q{Writing a bunch of case statements to handle regular expressions in method missing is just plain annoying. I suggest they get separated out and defined as their own methods. Well... ruby doesn't really let that happen, so this is the alternative.}
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",
@@ -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.included_modules.include?(Irregular::Method::InstanceMethods))
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
@@ -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
- - 2
7
+ - 3
8
8
  - 0
9
- version: 0.2.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-15 00:00:00 -04:00
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: Writing a bunch of case statements to handle regular expressions in method missing is just plain annoying. I suggest they get separated out and defined as their own methods. Well... ruby doesn't really let that happen, so this is the alternative.
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