Re: class destruction (evil genius metaprogramming)
by dblack other posts by this author
Jun 16 2007 3:32AM messages near this date
Re: class destruction (evil genius metaprogramming)
|
Re: class destruction (evil genius metaprogramming)
Hi --
On Sat, 16 Jun 2007, Giles Bowkett wrote:
> > > Why should this inspire fear?
> >
> > Code injection attack to own a RoR site possibly? That would be my guess.
>
> Sort of. I'm trying to use it to build a Rails plugin called
> acts_as_fox, which overrides every method on a model to return "chunky
> bacon!" (It's not really that terrifying, I just kind of had a Dr.
> Frankenstein moment, drunk on power type thing.)
>
> Unfortunately, applying Rick's code directly to an ActiveRecord model
> doesn't quite accomplish this, because it's missing the superclass
> methods, but applying it to ActiveRecord::Base doesn't work either. I
> did get it to work by doing it twice, both on the actual model and on
> ActiveRecord::Base itself, but that's very unsatisfying, because I
> solved the problem by cutting and pasting. (I think I understand why
> it worked; ActiveRecord::Base attaches a lot of methods to its
> subclasses, instead of having them inherited directly.) It also fails
> to really accomplish what I want to do, because it means that making
> one model acts_as_fox destroys all the other models. (I also need to
> attach a method_missing to return "chunky bacon!" but that part's
> obviously trivial.)
>
> Really the quickest way to accomplish this would be to simply pop the
> model out of its inheritance hierarchy - redefine the model not to
> have any superclass except Object - but I don't know if that's
> possible. Trying it in the most obvious way (class Foo < Object; end,
> where Foo was already defined Foo < ActiveRecord::Base) results in a
> TypeError with the message "superclass mismatch."
I do sometimes wonder what would happen if the ancestry array were
writeable. It could be interesting. I haven't thought through the
possible pitfalls.
> But there must be a clean way to open up the class, grab all its
> methods, including those derived from superclasses, and simply
> reassign them. Something like
>
> Foo.instance_methods(true).each{|m| Foo.instance_eval("alias
> :chunky_bacon " + m)}
Here's a little demo that does pretty much that (sparing the _ methods
like __send__):
class Object
def mask
puts "I'm masking a method"
end
end
class C
def x
puts "x"
end
def y
puts "y"
end
end
class D < C
def z
puts "z"
end
end
class D
instance_methods.reject {|m| /^_/.match(m) }.each do |m|
alias_method m, :mask
end
end
C.new.x # x
D.new.x # I'm masking a method
D.new.z # I'm masking a method
David
--
* Books:
RAILS ROUTING (new! http://safari.awprofessional.com/9780321509246)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
Thread:
Giles Bowkett
Rick DeNatale
dblack
Robert Dober
dblack
Robert Dober
Giles Bowkett
dblack
Stephen Smith
Nathan Taylor-Hoover
Giles Bowkett
dblack
Giles Bowkett
Rick DeNatale
dblack
Devin Mullins
dblack
Gregory Brown
Giles Bowkett
|