Skip to content

Commit

Permalink
FindBy mixin, to search arrays ala processes.find_by_pid(123)
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Wiggins committed Mar 8, 2008
1 parent 811f9b1 commit 3bf36c3
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/rush.rb
Expand Up @@ -13,6 +13,7 @@ module Rush::Connection; end
require 'dir'
require 'search_results'
require 'head_tail'
require 'find_by'
require 'string_ext'
require 'fixnum_ext'
require 'array_ext'
Expand Down
2 changes: 2 additions & 0 deletions lib/rush/array_ext.rb
Expand Up @@ -13,5 +13,7 @@ def entries
self
end

include Rush::FindBy

include Rush::HeadTail
end
37 changes: 37 additions & 0 deletions lib/rush/find_by.rb
@@ -0,0 +1,37 @@
# Generic find_by (returns first match) and find_all_by (returns all matches)
# against arrays.
#
# Examples:
#
# processes.find_by_pid(::Process.pid)
# processes.find_all_by_cmdline(/mongrel_rails/)
#
module Rush::FindBy
def method_missing(meth, *args)
if m = meth.to_s.match(/^find_by_([a-z_]+)$/)
find_by(m[1], args.first)
elsif m = meth.to_s.match(/^find_all_by_([a-z_]+)$/)
find_all_by(m[1], args.first)
end
end

def find_by(field, arg)
detect do |item|
item.respond_to?(field) and compare_or_match(item.send(field), arg)
end
end

def find_all_by(field, arg)
select do |item|
item.respond_to?(field) and compare_or_match(item.send(field), arg)
end
end

def compare_or_match(value, against)
if against.class == Regexp
value.match(against) ? true : false
else
value == against
end
end
end
55 changes: 55 additions & 0 deletions spec/find_by_spec.rb
@@ -0,0 +1,55 @@
require File.dirname(__FILE__) + '/base'

describe Rush::FindBy do
before do
class Foo
attr_accessor :bar

def initialize(bar)
@bar = bar
end
end

@one = Foo.new('one')
@two = Foo.new('two')
@three = Foo.new('three')

@list = [ @one, @two, @three ]
end

it "compare_or_match exact match success" do
@list.compare_or_match('1', '1').should == true
end

it "compare_or_match exact match failure" do
@list.compare_or_match('1', '2').should == false
end

it "compare_or_match regexp match success" do
@list.compare_or_match('123', /2/).should == true
end

it "compare_or_match regexp match failure" do
@list.compare_or_match('123', /x/).should == false
end

it "find_by_ extact match" do
@list.find_by_bar('two').should == @two
end

it "find_by_ regexp match" do
@list.find_by_bar(/.hree/).should == @three
end

it "find_all_by_ exact match" do
@list.find_all_by_bar('one').should == [ @one ]
end

it "find_all_by_ regexp match" do
@list.find_all_by_bar(/^...$/).should == [ @one, @two ]
end

it "find_by_ with field not recognized by objects raises no errors" do
@list.find_by_nothing('x')
end
end

0 comments on commit 3bf36c3

Please sign in to comment.