omninonsense
omninonsense

Reputation: 6882

Preventing methods from being re-defined

So, I need to make a method within a class protected from re-definition. I am not really sure how else to explain it so here's the code:

module Foo
    def bar
        p "lol"
    end
end

Now, that's the original Foo#bar method and I need it to be like a constant. So, I did come up with a solution. That was to save the method in a Constant and detect when someone tried changing it it would simply re-load it from that constant (it was a Proc object):

module Foo
        Original_bar = Proc.new { p "lol" }

        def bar
            Original_bar.call
        end

        def self.method_added(method_name)
            if method_name == :bar
                def Foo::bar
                    Original_bar.call
                end
            end
        end
end

But this isn't completely safe since once could use the same "trick" I did to bypass method_added and I am not really fond of this, since it's not very ruby-like.


Tests

A normal test:

module Foo
    def bar
        p "lmao"
    end
end

Foo::bar # => "lol"

And another test using the trick:

def Foo::bar
    p "rofl"
end

Foo::bar # => "rofl"

tl;dr

How to make a method in Ruby "unredefinable" (if that's even a word)?

Upvotes: 1

Views: 414

Answers (2)

Andrew Grimm
Andrew Grimm

Reputation: 81510

You can make your code warn you that a method has been over-ridden by turning on warnings:

$VERBOSE = true

module Foo
  def self.bar
    p "lmao"
  end
end

def Foo::bar
    p "rofl"
end

(irb):9: warning: method redefined; discarding old bar

It may be possible, but not practical, to raise an exception when warnings are issued.

This won't warn you if you first undefine Foo.bar, however.

Upvotes: 0

Frederick Cheung
Frederick Cheung

Reputation: 84114

If you freeze the module that should prevent method being added to it.

Note that a c extension can unfreeze variables (see evil.rb for example.

Upvotes: 1

Related Questions