I’ve seen this work before:
module MagicWithMethodMissing
alias_method :__orig_method_missing, :method_missing
def method_missing(sym, *args, &block)
if some_condition
#do special stuff
else
__orig_method_missing(sym, *args, &block)
end
end
end
class MyClass
include MagicWithMethodMissing
end
I want to do the same thing w/ :new on the class
module MagicWithNew
alias_method :__orig_new, :new
def new(*args, &block)
if some_condition
#do special stuff
else
__orig_new(*args, &block)
end
end
end
The question I have is how do I get this included in the meta class
of MyClass?
Thanks,
David
On Jul 12, 2006, at 12:07 AM, David C. wrote:
end
def new(*args, &block)
Thanks,
David
Couple of things
-
alias_method gets executed at “compile” time. This means that it
will try to alias MagicWithNew.
-
This is ok because you dont want to use alias’s in this case.
Since #new is almost never overriden (it’s usually #initialize.
Incidentally are you sure you don’t want to define #initialize
instead?) it’s pretty much guaranteed that you class is using the
original implementation in Class.
so we can use inheritance and super
module MagicWithNew
def new(*args, &block)
if some_condition
do_special_stuff
else
super
end
end
end
class MyClass
extend MagicWithNew # note #extend, not #include
end
On Wed, 12 Jul 2006, Logan C. wrote:
module MagicWithNew
def new(*args, &block)
if some_condition
do_special_stuff
fails to initialize object! you need the old ‘new’ here. or super.
else
super
end
end
end
class MyClass
extend MagicWithNew # note #extend, not #include
end
here is an example of a fairly robust pattern
harp:~ > cat a.rb
module M
ClassMethods = lambda do
alias_method ‘new’, ‘new’ # correct alias of new
def new *a, &b
obj = __new__(*a, &b)
#
# do anything you want with obj here based on any condition.
this is just
# an example.
#
class << obj
def answer() 42 end
end
obj
end
end
def self.included other
meta =
class << other
self
end
meta.module_eval &ClassMethods
super
end
end
class C
include M
end
p C.new.answer
harp:~ > ruby a.rb
42
regards.
-a
On Jul 12, 2006, at 1:01 AM, [email protected] wrote:
original implementation in Class.
so we can use inheritance and super
module MagicWithNew
def new(*args, &block)
if some_condition
do_special_stuff
fails to initialize object! you need the old ‘new’ here. or super.
Well he did say “special stuff”. He only needs old new or super there
if he plans on initializing the object 
On Jul 12, 2006, at 12:15 AM, Logan C. wrote:
Well he did say “special stuff”. He only needs old new or super
there if he plans on initializing the object 
Yes. I’m writing an acts_as_mock plugin for rails controller tests.
Since activerecord relies on a bunch of class methods, I need to be
able to mock them as well so I can write tests like this:
def test_blah
expected = Story.new
Story.should_receive(:new).and_return(expected)
expected.should_receive(:some_message)
get :blah
end
This (in theory) will allow us to run controller (functional) tests
in isolation (i.e. no DB necessary), and therefore much faster.
In the example above, the first call to :new gets handled by super.
The second line tells the class that the next time :new is called, it
should return this particular object (expected). After that, you can
set expectations on expected.
Thanks to your help here, this is working like a charm!
I’ve got a lot more work to do on this to make it even alpha-release
worthy, but I’ll post a note here when I get there.
Cheers,
David
David C. wrote:
On Jul 12, 2006, at 12:15 AM, Logan C. wrote:
Yes. I’m writing an acts_as_mock plugin for rails controller tests.
Since activerecord relies on a bunch of class methods, I need to be
able to mock them as well so I can write tests like this:
def test_blah
expected = Story.new
Story.should_receive(:new).and_return(expected)
expected.should_receive(:some_message)
get :blah
end
This (in theory) will allow us to run controller (functional) tests
in isolation (i.e. no DB necessary), and therefore much faster.
Sounds interesting. I’ve been working on something similar - a mocking
library called Mocha (http://mocha.rubyforge.org). It’s not specifically
targetted at Rails controller tests, but I think the Stubba/AutoMocha
parts might allow you to do what you want.
Stubba allows you to mock or stub class methods.
For AutoMocha, I alias the :new method in Mocha:MockClass
(http://mocha.rubyforge.org/classes/Mocha/MockClass.html) and define a
new version that delegates to method_missing which is at the heart of
the mocking functionality. The inherited method then ensures that any
subclasses get the original :new method back.
James.