require 'rubygems'Another example is the Rails
require 'spec'
module DynamicGetter
def method_missing(name, *args)
if(@attributes.has_key? name)
self.class.class_eval do
define_method(name){ @attributes[name] }
end
self.send(name, *args)
else
super
end
end
end
describe DynamicGetter do
before(:each) do
# Reference the class used in the specs
# as an ordinary variable rather than a
# named constant (@ooga instead of Ooga)
# so that it can be created afresh for
# each spec.
# If we did class Ooga, the second spec
# would fail because the first spec already
# created the method #woot.
@ooga_klass = Class.new(Object)
@ooga_klass.class_eval do
include DynamicGetter
def initialize(attributes = {})
@attributes = attributes
end
end
end
it "should know how to add a method to a class on first call" do
o = @ooga_klass.new(:woot => 5)
o.should_not respond_to(:woot)
o.woot.should == 5
o.should respond_to(:woot)
end
it "should raise a method not found exception if the attribute isn't present" do
lambda{ @ooga_klass.new.woot }.should raise_error(NoMethodError)
end
end
find_by_*
methods, which are defined the first time you call them.If, for some reason, you want to apply the example I've given on a per-instance basis, look at this post.
Related posts:
2 comments:
the raising of NoMethodError can be replaced with a call to super() and ruby will throw the error for you plus less code to maintain :)
There is much wisdom in what you say. It is done.
Post a Comment