Skip to content

Instantly share code, notes, and snippets.

@ericbeland
Created February 23, 2011 16:57
Show Gist options
  • Save ericbeland/840710 to your computer and use it in GitHub Desktop.
Save ericbeland/840710 to your computer and use it in GitHub Desktop.
Invisibly call methods on all array members
# The invisible proxy allows seamless calling of a method on all objects of an array.
# When an array is wrapped (passed into) one of these objects, you can call a function
# on all objects in the array with one line. Useful for dsl's and such.
class InvisibleProxyToArray
instance_methods.each do |m|
undef_method(m) unless m =~ /(^__|^nil\\?|object_id|^send)/
end
def initialize(collection)
@collection = collection
end
def respond_to?(symbol)
@collection.first.respond_to?(symbol)
end
# calls a method on every member of the proxied array
# and totals the return values
def total(total_symbol)
@collection.inject(0){|tot, obj| tot + obj.send(total_symbol)}
end
# gives a string indicating object responses to being sent a symbol (which calls a property or method)
# summarize(:status) will produce: running (2), stopping (13)
def summarize(summarize_symbol)
msgs=[]
hsh=hash_by_result(summarize_symbol, @collection)
hsh.each {|status, resources_arr| msgs << "#{status}: #{resources_arr.length}"}
msgs.join(', ')
end
# returns a hash like {"running"=>[a , b], "dead"=>[a]} for :status or other messages
# where a and b would be resources whose response for :status was "running"
def hash_by_result(property_symbol, object_array)
hsh={}
object_array.each do |obj|
val = obj.send(property_symbol)
hsh[val] ||= []
hsh[val] << obj
end
hsh
end
private
def method_missing(method, *args, &block)
@collection.each {|item| item.send(method, *args, &block)}
end
end
# a toy to demonstrate
class Thing
attr_reader :value
def initialize(value)
@value=value
end
def say_num
puts "My value is: #{@value}"
end
def status
['pillow talk, baby','chewing bubblegum', 'kicking ass'].sample
end
end
mythings=InvisibleProxyToArray.new([Thing.new(9), Thing.new(10), Thing.new(9), Thing.new(11)])
puts "total: #{mythings.total(:value)}"
puts "summarize: #{mythings.summarize(:status)}"
puts "the fun part--call a method on all members with one line and no block"
mythings.say_num
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment