[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: alias new???

Logan Capaldo

7/12/2006 4:50:00 AM


On Jul 12, 2006, at 12:07 AM, David Chelimsky wrote:

> 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
>
>
>

Couple of things
1) alias_method gets executed at "compile" time. This means that it
will try to alias MagicWithNew.

2) 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




4 Answers

Ara.T.Howard

7/12/2006 5:01:00 AM

0

Logan Capaldo

7/12/2006 5:15:00 AM

0


On Jul 12, 2006, at 1:01 AM, ara.t.howard@noaa.gov wrote:

> On Wed, 12 Jul 2006, Logan Capaldo wrote:
>
>> Couple of things
>> 1) alias_method gets executed at "compile" time. This means that
>> it will try to alias MagicWithNew.
>>
>> 2) 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
>
> 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 ;)

>
>> 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
> --
> suffering increases your inner strength. also, the wishing for
> suffering
> makes the suffering disappear.
> - h.h. the 14th dali lama
>


David Chelimsky

7/12/2006 10:56:00 AM

0

On Jul 12, 2006, at 12:15 AM, Logan Capaldo wrote:
> On Jul 12, 2006, at 1:01 AM, ara.t.howard@noaa.gov wrote:
>> On Wed, 12 Jul 2006, Logan Capaldo 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.
>>
> 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





James Mead

7/17/2006 9:35:00 AM

0

David Chelimsky wrote:
> On Jul 12, 2006, at 12:15 AM, Logan Capaldo 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.rub...). 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.rub.../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.

--
Posted via http://www.ruby-....