class WrapMany
Adapted from gist.github.com/1120383
Wraps multiple objects in a single object. Method calls are resolved by cycling through all wrapped objects, in the order they were specified on the constructor, looking for the appropriate named method. Useful for temporarily adding methods to an instance, without monkeypatching the class.
WrapMany has special-case logic for OpenStruct objects, Hash objects and object fields. Hash keys, OpenStruct fields, and public instance variables will be resolved, but only for calls made with no parameters.
Example 1: Add an “age” value to a User object using an OpenStruct
require 'ostruct' require 'grizzled/wrapmany' age_holder = OpenStruct.new(:age => 43) u = User.find(...) user_with_age = WrapMany.new(u, age_holder)
Example 2: Add an “age” value to a User object using a hash
require 'grizzled/wrapmany' u = User.find(...) user_with_age = WrapMany.new(u, {:age => 43})
Example 3: Add an “age” value to a User object using another class
require 'grizzled/wrapmany' class AgeHolder def initialize(age) @age = age end end u = User.find(...) user_with_age = WrapMany.new(u, AgeHolder.new(43))
Public Class Methods
new(*args)
click to toggle source
# File lib/grizzled/wrapmany.rb, line 44 def initialize(*args) # Map any OpenStruct objects in the arguments to hashes, and add the # current object (in case someone subclasses this class) @objects = args.to_a.map { |a| a.is_a?(OpenStruct) ? a.instance_variable_get("@table") : a } + [self] end
Public Instance Methods
method_missing(meth, *args, &block)
click to toggle source
# File lib/grizzled/wrapmany.rb, line 52 def method_missing(meth, *args, &block) method_name = meth.to_s # Loop through all objects, looking for something that satisfies the # method name. @objects.each do |o| # First determine if the method exists as a public instance method. # If so, call it. if o.class.public_instance_methods.include? method_name.to_sym return o.send(method_name, *args, &block) end # Otherwise, if there are no arguments, then check for fields and # hash keys if args.length == 0 if o.instance_variables.include? ":@#{method_name}" return o.instance_variable_get method_name end # Special case for hash if o.is_a? Hash if o.has_key? meth return o[meth] elsif o.has_key? method_name return o[method_name] end end end end raise NoMethodError.new("Undefined method: '#{method_name}'", meth) end