From: aurelianito Date: 2005-10-09T07:36:51+09:00 Subject: Re: Method added hook > Regarding the method hooks, one thing that you can do to complicate things > somewhat is to do something like this (not tested): > > class SomeClass > def some_method(*a, &b) > # ... > end > > alias_method :__safety__, :some_method > > def self.method_added(sym) > unless @my_add > # Revert back to original > if sym == :some_method > alias_method :some_method, :__safety__ > end > else > @my_add = false > end > end > end Uou! Something like this is what I'm looking for! I can build my ClassModificationPermission (or something like that) from this! > However, the problem is that the user may simply #undef_method your > #method_added or do something equivalent. It is a neverending cycle. > #freeze helps a bit but there is a way around it, too. I may define the self.method_removed method to prevent the removal (doing the same trick). > irb(main):001:0> class Foo > irb(main):002:1> def foo > irb(main):003:2> puts 'foo' > irb(main):004:2> end > irb(main):005:1> end > => nil > irb(main):006:0> Foo.freeze > => Foo > irb(main):007:0> class Foo > irb(main):008:1> def foo > irb(main):009:2> puts 'foo' > irb(main):010:2> end > irb(main):011:1> end > TypeError: can't modify frozen class > from (irb):8 > irb(main):012:0> x = Foo.dup > => # > irb(main):013:0> Foo = x > (irb):13: warning: already initialized constant Foo > => Foo > irb(main):014:0> class Foo > irb(main):015:1> def foo > irb(main):016:2> puts 'bar' > irb(main):017:2> end > irb(main):018:1> end > => nil > irb(main):019:0> Foo.new.foo > bar > => nil > irb(main):020:0> Isn't there a callback method for constant assignament? I'll look for it. If that's the case, I can do the same trick (again). > The only thing you can do is to modify the Ruby interpreter. You will > need to hook into the method table modification code and intercept all > those calls. Then, for each call, inspect the arguments and no-op any > attempts to modify some defined methods (you should probably allow this > to be configurable). I'm trying not to modify the ruby interpreter. I want a pure Ruby solution. I've been thinking to make my (future) lib a gem and distribute this way. If I have to modify it, I've been thinking two choices: 1 - Add pre-event callbacks to all the operations I need to prevent. (It should be as simpler than your solution, but I'm just guessing). These callbacks should be thread safe. Then I would implement the permission check in these hooks. 2 - Force def, class, module and = to be METHODS. If they were methods I would just redefine them to check if the operation is allowed and call the older method. This would be pure ruby code (unless there is a serious performance issue). Thank's for your input, now I have something to try. Aureliano.