Skip to content

Instantly share code, notes, and snippets.

@Floppy
Created August 1, 2012 16:11
Show Gist options
  • Save Floppy/3228297 to your computer and use it in GitHub Desktop.
Save Floppy/3228297 to your computer and use it in GitHub Desktop.
ActiveRecord-style array filtering
#!/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