Created
August 1, 2012 16:11
-
-
Save Floppy/3228297 to your computer and use it in GitHub Desktop.
ActiveRecord-style array filtering
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# ArrayExt shows how to extend Array to support activerecord-style | |
# filter chaining. | |
class ArrayExt | |
# When we create the ArrayExt, we store the actual array | |
# we want to operate on internally | |
def initialize(finder) | |
# Store delegation object | |
@array = finder.to_a | |
end | |
# We don't use Ruby's built-in delegation, because then filters | |
# would return Array objects, not ArrayExt objects, so we have to | |
# delegate manually through method_missing | |
def method_missing(*args, &block) | |
# Delegate to wrapped array | |
r = @array.send(*args, &block) | |
# Return an ArrayExt, not a standard array, if the result is an array | |
if r.is_a?(Array) | |
ArrayExt.new(r) | |
else | |
r | |
end | |
end | |
# We can then create our filters. Calling 'self' is important here. | |
# ArrayExt#select doesn't exist, and Kernel#select will be called | |
# instead, before ArrayExt#method_missing, so we have to force it. | |
def single_digits | |
self.select {|x| x < 10} | |
end | |
def more_than_five | |
self.select {|x| x > 5} | |
end | |
end | |
x = ArrayExt.new [3,7,12,1,34] | |
puts x.single_digits.inspect | |
# => #<ArrayExt:0x007fef688461d8 @array=[3, 7, 1]> | |
puts x.more_than_five.inspect | |
# => #<ArrayExt:0x007fef68845e18 @array=[7, 12, 34]> | |
# The filters can be chained just like you would with activerecord - win! | |
puts x.single_digits.more_than_five.inspect | |
# => #<ArrayExt:0x007fef68845e18 @array=[7]> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment