Method_missing - but can it be "isolated" to per-project basis?

Hi.

I have been playing with the following code (explanation follows after
the code):

···

------------------------------

  require 'pp'

  class Object
    def method_missing(*args)
      return args.join ' '
    end
  end

  def foo(i = nil)
    puts i if i
    puts yield if block_given?
  end

  foo
  foo 'testing 1'
  foo { 'testing 2' }
  foo { testing 3 }

  # The code above returns:
  # testing 1
  # testing 2
  # testing 3

------------------------------

Ok, this code defines method foo, and we use 4 different ways to
call it.

What I was most interested in was the last version - I want to access
all what was passed in a block as string. This is useful for one
project, but it is not good to modify Object in such a way in larger
projects.

Any advice on whether it is possible to keep this piece of code only on
a per-project basis? Like, I want to extend class Object only in the
context of that specific object, but if I use it in a larger project, I
don't want to use that very modification to class Object (because,
outside that project, it would be counter-productive to act on
method_missing that way).

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

Not exactly sure what you are trying to accomplish, but you could create a
base class for your project and use it where ever it is needed.

  module MyLib
     class Base
      def method_missing(*args)
        return args.join ' '
      end
    end

    class Foo < Base
       ...
    end
  end

require 'pp'

You require pp but never use it.

class Object
   def method_missing(*args)

O.o be careful with this, it's likely to end in misery.

Any advice on whether it is possible to keep this piece of code only on
a per-project basis? Like, I want to extend class Object only in the
context of that specific object, but if I use it in a larger project, I
don't want to use that very modification to class Object (because,
outside that project, it would be counter-productive to act on
method_missing that way).

It's unclear to me what you mean by "I want to extend class Object only in
the context of that specific object". Here are some ways to deal with this
sort of thing that might be helpful (I can't really even think of a use
case for this, maybe if you explain what you're really trying to do, a
better solution can be offered).

1) Just rescue the exception. (recommended)

begin
  Object.new.abc(123)
rescue NoMethodError => e
  puts "#{e.name} #{e.args.join ' '}"
end
# >> abc 123

2) Extend just the object you want to do this to. I don't dig it, but at
least the crazy is contained to just that object. Note that methods not on
this object will still behave as normal (even if invoked by a method on
this object)

module CrazyMethodMissing
  def method_missing(*args)
    args.join ' '
  end
end

Object.new.extend(CrazyMethodMissing).abc(123) # => "abc 123"
Object.new.abc(123) # ~> -:8:in `<main>': undefined method `abc' for
#<Object:0x0b50a4> (NoMethodError)

3) Conditionally switch this behaviour on and off with a global variable
(highly discouraged, and if you made library code which did this -- what I
assume you mean by the "project" comments -- then I would be quite
displeased when I found out).

class Object
  def method_missing(*args)
    return super if $neverdie.zero?
    args.map(&:to_s).join ' '
  end

  $neverdie = 0
  def neverdie(&block)
    $neverdie += 1
    instance_eval &block
  ensure
    $neverdie -= 1
  end
end

Object.new.neverdie { abc 123 } # => "abc 123"
Object.new.abc 123
# ~> -:3:in `method_missing': undefined method `abc' for #<Object:0x0b494c>
(NoMethodError)
# ~> from -:17:in `<main>'

···

On Fri, Jan 27, 2012 at 4:06 PM, Marc Heiler <shevegen@linuxmail.org> wrote: