How do I catch a missing method on a passed block?

I would like to invoke method_missing on baz in this code;

x = Foo.new
x.bar { baz }

I tried the following, and although the method is added to the proc
objects singleton class, the method_missing method never gets called.
Is there any way to achieve this? My current code (that doesn't work)
is below;

class Foo

  def bar(*values, &block)

    if block_given?

      class << block
        def method_missing(m, *args, &block)
          puts "missing #{m}"
        end
      end

      block.call

    end
  end
end

but block __will__ respond_to? 'call' - ergo your method_missing hook will
never fire? what are you trying to do?

-a

···

On Tue, 5 Dec 2006, J2M wrote:

I would like to invoke method_missing on baz in this code;

x = Foo.new
x.bar { baz }

I tried the following, and although the method is added to the proc
objects singleton class, the method_missing method never gets called.
Is there any way to achieve this? My current code (that doesn't work)
is below;

class Foo

def bar(*values, &block)

   if block_given?

     class << block
       def method_missing(m, *args, &block)
         puts "missing #{m}"
       end
     end

     block.call

   end
end
end

--
if you want others to be happy, practice compassion.
if you want to be happy, practice compassion. -- the dalai lama

I would like to invoke method_missing on baz in this code;

x = Foo.new
x.bar { baz }

I tried the following, and although the method is added to the proc
objects singleton class, the method_missing method never gets called.
Is there any way to achieve this? My current code (that doesn't work)
is below;

You'd want to define the method_missing
<--- here
x.bar { baz }

Obviously that's not always practical, so what you need to do is change
self. That can be acheived by using #instance_eval. This has
disadvantages, obviously, but that's how to do it if you want to do it.

Or you can pass a parameter into the block:
x.bar { |q| q.baz }

···

On Tue, Dec 05, 2006 at 08:04:33AM +0900, J2M wrote:

class Foo

  def bar(*values, &block)

    if block_given?

      class << block
        def method_missing(m, *args, &block)
          puts "missing #{m}"
        end
      end

      block.call

    end
  end
end

class Foo
    def bar
      yield
    rescue NoMethodError => error
      # mojo goes here
    end
  end

Cheers,
Daniel

···

On Tue, 2006-12-05 at 08:04 +0900, J2M wrote:

I would like to invoke method_missing on baz in this code;

x = Foo.new
x.bar { baz }

I tried the following, and although the method is added to the proc
objects singleton class, the method_missing method never gets called.
Is there any way to achieve this? My current code (that doesn't work)
is below;

class Foo

  def bar(*values, &block)

    if block_given?

      class << block
        def method_missing(m, *args, &block)
          puts "missing #{m}"
        end
      end

      block.call

    end
  end
end

I've some comments, on almost all code in this thread. Feel
free to ignore me...

All code is "polluted" with meta-code stuff and "class <<
object" stuff and "instance_eval" stuff and "class_eval" stuff
and other stuff. That doesn't feel good. Well, you need this
code to do the trick, but...

It's usually a good idea to separate business logic and low
level code. The novice programmers and mediocre programmers can
concentrate on the business level code, while the more seasoned
programmer can write the low-level code. The novice programmer
is the user of the code made by the smart guy.

The novice programmer only sees clean code: He understands what
he is doing and is happy. Smart Guy is the, well, uh, smart guy
and is happy too. Everybody's happy!

I've mixed business code and low-level code myself, in the
past. After one month, I simply couldn't read my own code,
solely because I was mixing both levels. So, even if you are a
smart guy and the only developer, it's still a good idea to
think and code on different levels.

I've rewritten one of the examples. Lines 1-12 are (is?)
low-level code (generic) and can and should be hidden in a
library. Lines 14-28 are (is?) the business code (non-generic).

On line 16, we wrap the received block, which could easily be
commented out, if necessary. Method_missing_inspect calls
block_with_method_missing with the given block and a
(non-generic) method_missing block. Block_with_method_missing
enriches the given block1 with a method_missing (which is
implemented by block2) and returns the enriched block1.

The result is that Foo#bar, the business logic, is still very
clean and very readable. Method_missing_inspect is a bit more
sophisticated, but still understandable for Joe Average.
Block_with_method_missing is the work of Smart A^HGuy...

Just my thoughts. Ignore me, if appropriate...

gegroet,
Erik V. - http://www.erikveen.dds.nl/

···

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

     1 module Kernel
     2 def block_with_method_missing(block1, &block2)
     3 class << block1
     4 self
     5 end.module_eval do
     6 define_method(:method_missing, &block2)
     7 define_method(:call){block1.instance_eval(&block1)}
     8 end
     9
    10 block1
    11 end
    12 end
    13
    14 class Foo
    15 def bar(&block)
    16 block = method_missing_inspect(block)
    17
    18 block.call
    19 end
    20
    21 def method_missing_inspect(block)
    22 block_with_method_missing(block) do |method_name, *args|
    23 p [:mm, method_name, args]
    24 end
    25 end
    26 end
    27
    28 Foo.new.bar{baz(1, 2, 3)}

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

I want to catch a missing method (baz) inside the passed block.

Thanks,
James

···

ara.t.howard@noaa.gov wrote:

but block __will__ respond_to? 'call' - ergo your method_missing hook will
never fire? what are you trying to do?

Logan Capaldo wrote:

Or you can pass a parameter into the block:
x.bar { |q| q.baz }

Thanks Logan, that is what I ended up doing, I just wanted to avoid
having to pass the parameter if it was at all possible. I am writing a
dsl so wanted it to be as clean as possible e.g.

define_stuff do
  this :option => "something"
  that :option => "something else"
  the_other :option => "and something else"
end

Thanks,
James

> I would like to invoke method_missing on baz in this code;
>
> x = Foo.new
> x.bar { baz }
>
> I tried the following, and although the method is added to the proc
> objects singleton class, the method_missing method never gets called.
> Is there any way to achieve this? My current code (that doesn't work)
> is below;
>
> class Foo
>
> def bar(*values, &block)
>
> if block_given?
>
> class << block
> def method_missing(m, *args, &block)
> puts "missing #{m}"
> end
> end
>
> block.call
>
> end
> end
> end

  class Foo
    def bar
      yield
    rescue NoMethodError => error
      # mojo goes here
    end
  end

If ruby were common lisp, that could actually work. But it's not and our
exceptions are not resuamble :).

···

On Tue, Dec 05, 2006 at 11:54:06PM +0900, Daniel Schierbeck wrote:

On Tue, 2006-12-05 at 08:04 +0900, J2M wrote:

Cheers,
Daniel

Erik Veenstra wrote:

I've some comments, on almost all code in this thread. Feel
free to ignore me...

All code is "polluted" with meta-code stuff and "class <<
object" stuff and "instance_eval" stuff and "class_eval" stuff
and other stuff. That doesn't feel good. Well, you need this
code to do the trick, but...

It's usually a good idea to separate business logic and low
level code. The novice programmers and mediocre programmers can
concentrate on the business level code, while the more seasoned
programmer can write the low-level code. The novice programmer
is the user of the code made by the smart guy.

The novice programmer only sees clean code: He understands what
he is doing and is happy. Smart Guy is the, well, uh, smart guy
and is happy too. Everybody's happy!

I've mixed business code and low-level code myself, in the
past. After one month, I simply couldn't read my own code,
solely because I was mixing both levels. So, even if you are a
smart guy and the only developer, it's still a good idea to
think and code on different levels.

--- snip ---

Erik, thank you for pre-empting my next challenge and giving me a good
lesson in structure. Making the transition from mediocre to smart could
be more about structuring the code than knowing the language better :wink:

James

Hi --

I've some comments, on almost all code in this thread. Feel
free to ignore me...

All code is "polluted" with meta-code stuff and "class <<
object" stuff and "instance_eval" stuff and "class_eval" stuff
and other stuff. That doesn't feel good. Well, you need this
code to do the trick, but...

I guess "polluted" is relative. I admit I've never understood the
fuss that people make over these things, one way or the other -- that
is, I neither see them as a badge of some kind of wizardry, nor think
that they are to be shunned or stigmatized. They're just ways to live
productively in the Ruby landscape, where there are objects and
objects have singleton classes and there's a 'self' and so on. I
guess class << obj requires more ramping up than x = 1, but on the
whole I think Ruby is much flatter than it's often given credit for.

Most of what people need to grasp and embrace, in order to understand
and use the vast bulk of these techniques, and others, is:

   * classes are objects
   * each object (or almost each object) has both a "birth class" and a
     singleton class
   * objects don't have methods; they look for them along a
     class/module search path, with well-defined rules of order and
     inclusion
   * there's one and only one 'self' at every point in the program
   * instance variables belong to 'self', always
   * class variables are completely unrelated to instance variables,
     in spite of the use of @ in one and @@ in the other
   * the def and class keywords start new local scopes
   * the class keyword can take either a constant (for a named class)
     or a "<< object" expression (for a singleton class)

I'm not saying that's the whole language, of course; but probably
about 90% of the problems I've seen people have with Ruby over the
years -- with the language generally, with understanding code they
see, and with solving specific problems in their own code -- come from
not understanding one or more of these points. Class variables are
perhaps the worst offenders: they cause no end of confusion. The role
of 'self', particularly as it governs ownership of instance variables,
is also a bit of a hurdle -- but not insurmountable.

I'm all for organizing code nicely, and grouping together things that
belong together, as you suggest. But what's been concerning me
recently is that it feels like people are being encouraged to feel
awestruck and out of their depth when they see "class << object".
Yes, it looks different from "class C" but I just don't think it's
*that* big a deal. The underlying principles are relatively few; the
language is expressive; and it all works together rather nicely.

David

···

On Wed, 13 Dec 2006, Erik Veenstra wrote:

--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

here's how to catch it:

   harp:~ > cat a.rb
   class Foo
     def bar *a, &b
       if b
         singleton_class = class << b; self; end
         singleton_class.module_eval{
           def method_missing m, *a, &b
             p [m, a, b]
           end
         }
         b.instance_eval &b
       end
     end
   end

   Foo.new.bar{ baz }

   harp:~ > ruby a.rb
   [:baz, , nil]

and here's how to forward it to another object, in this case the Foo object:

   harp:~ > cat a.rb
   class Foo
     def bar *a, &b
       if b
         this = self
         singleton_class = class << b; self; end
         singleton_class.module_eval{
           @@this = this
           def method_missing m, *a, &b
             @@this.send m, *a, &b
           end
         }
         b.instance_eval &b
       end
     end

     def baz
       p 'baz'
     end
   end

   Foo.new.bar{ baz }

   harp:~ > ruby a.rb
   "baz"

there are many ways to skin that cat. can you start out by just telling us
__exactly__ what you want are trying to do? the various ways of solving this
each have consequences which could more easily be chosen from if we knew.

kind regards.

-a

···

On Tue, 5 Dec 2006, J2M wrote:

ara.t.howard@noaa.gov wrote:

but block __will__ respond_to? 'call' - ergo your method_missing hook will
never fire? what are you trying to do?

I want to catch a missing method (baz) inside the passed block.

--
if you want others to be happy, practice compassion.
if you want to be happy, practice compassion. -- the dalai lama

Logan Capaldo wrote:

>
> class Foo
> def bar
> yield
> rescue NoMethodError => error
> # mojo goes here
> end
> end
>
If ruby were common lisp, that could actually work. But it's not and our
exceptions are not resuamble :).

class Foo
  def bar
    yield
  rescue NameError => method_call
    p method_call.name
  end
end

Foo.new.bar { baz }

···

On Tue, Dec 05, 2006 at 11:54:06PM +0900, Daniel Schierbeck wrote:

dblack@wobblini.net wrote:

Most of what people need to grasp and embrace, in order to understand
and use the vast bulk of these techniques, and others, is:

   * classes are objects
   * each object (or almost each object) has both a "birth class" and a
     singleton class
   * objects don't have methods; they look for them along a
     class/module search path, with well-defined rules of order and
     inclusion
   * there's one and only one 'self' at every point in the program
   * instance variables belong to 'self', always
   * class variables are completely unrelated to instance variables,
     in spite of the use of @ in one and @@ in the other
   * the def and class keywords start new local scopes
   * the class keyword can take either a constant (for a named class)
     or a "<< object" expression (for a singleton class)

This is a useful summary of the key concepts that moved me forward. I
have a long way to go, but it clearly encapsulates the crossing of a
rubicon (sic).

I'm not saying that's the whole language, of course; but probably
about 90% of the problems I've seen people have with Ruby over the
years -- with the language generally, with understanding code they
see, and with solving specific problems in their own code -- come from
not understanding one or more of these points. Class variables are
perhaps the worst offenders: they cause no end of confusion. The role
of 'self', particularly as it governs ownership of instance variables,
is also a bit of a hurdle -- but not insurmountable.

Absolutely, the questions I raised on this thread were founded in a
need to know how to apply these concepts, which is why everybody's
feedback has been incredibly valuable. I may have grasped the concepts
but the application takes a little longer.

I'm all for organizing code nicely, and grouping together things that
belong together, as you suggest. But what's been concerning me
recently is that it feels like people are being encouraged to feel
awestruck and out of their depth when they see "class << object".
Yes, it looks different from "class C" but I just don't think it's
*that* big a deal. The underlying principles are relatively few; the
language is expressive; and it all works together rather nicely.

Erik's code offered a clean way of extracting some of the aspects that
can be re-used, whether I call the remaining code business logic or not
in this example is irrelevant, but it does present a neat way of
structuring things but being reminded that I have a lot to learn
doesn't always feel great!

The big lesson I got from Erik was in reflecting on both your comments
and Erik's example code is the clarity of understanding comes from the
ability to grasp and reflect on a number of principles concurrently.
That can be a very hard thing to do - keeping all those principles in
mind at the same time. Breaking the code into those 3 methods helped
encapsulate those concepts in a way that was less effort to think
about. To me it wasn't about inspiring awe but rather removing the
complexity.

James

Most of what people need to grasp and embrace, in order to understand
and use the vast bulk of these techniques, and others, is:

   * classes are objects
   * each object (or almost each object) has both a "birth class" and a
     singleton class
   * objects don't have methods; they look for them along a
     class/module search path, with well-defined rules of order and
     inclusion
   * there's one and only one 'self' at every point in the program
   * instance variables belong to 'self', always
   * class variables are completely unrelated to instance variables,
     in spite of the use of @ in one and @@ in the other
   * the def and class keywords start new local scopes
   * the class keyword can take either a constant (for a named class)
     or a "<< object" expression (for a singleton class)

I have to admit, I don't understand what this means in practical
terms. In fact I have a question I need to find an answer to, and I
want to post it in this thread, rather than as its own thing, in the
possibly idealistic hope that somebody can frame an answer in terms of
these principles, and help me understand them.

Basically, I need to change a class method. It's the Ferret method
full_text_search, in a Rails app.

e.g.:

Thing.full_text_search("asdf")

I need to modify this class method. I tried alias, but did it wrong.

alias original_full_text_search full_text_search

but of course it doesn't work, because it's not an instance method but
a class method. Is this a good place for class_eval? I could be way
off.

Actually now that I re-read it, I think I do understand the basic
concepts, I think I'm just weak on the syntax.

···

--
Giles Bowkett
http://www.gilesgoatboy.org

http://gilesgoatboy.blogspot.com

-a ! Thanks, I will give this a shot. I really appreciate your help.
James

Breaks:

irb(main):008:0> a = Foo.new
=> #<Foo:0x2b301a826778>
irb(main):009:0> a.bar { baz }
:baz
=> nil
irb(main):010:0> a.bar { baz; quux }
:baz
=> nil

martin

···

On 12/6/06, Tim Fletcher <twoggle@gmail.com> wrote:

Logan Capaldo wrote:
> >
> If ruby were common lisp, that could actually work. But it's not and our
> exceptions are not resuamble :).

class Foo
  def bar
    yield
  rescue NameError => method_call
    p method_call.name
  end
end

Foo.new.bar { baz }

Hi --

Erik's code offered a clean way of extracting some of the aspects that
can be re-used, whether I call the remaining code business logic or not
in this example is irrelevant, but it does present a neat way of
structuring things but being reminded that I have a lot to learn
doesn't always feel great!

The big lesson I got from Erik was in reflecting on both your comments
and Erik's example code is the clarity of understanding comes from the
ability to grasp and reflect on a number of principles concurrently.
That can be a very hard thing to do - keeping all those principles in
mind at the same time. Breaking the code into those 3 methods helped
encapsulate those concepts in a way that was less effort to think
about. To me it wasn't about inspiring awe but rather removing the
complexity.

Definitely. I think breaking the code down is fine (I might avoid
adding to Kernel, but that's another story :slight_smile: I was chiming in more
on some of the stuff Erik raised by way of context. And of course
there's a long history of the dividing of "regular" from "meta" in
Ruby, and a fairly long history of my skepticism of it. Erik's post
just put me in mind of the whole thing.

David

···

On Wed, 13 Dec 2006, J2M wrote:

--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Hi --

Most of what people need to grasp and embrace, in order to understand
and use the vast bulk of these techniques, and others, is:

   * classes are objects
   * each object (or almost each object) has both a "birth class" and a
     singleton class
   * objects don't have methods; they look for them along a
     class/module search path, with well-defined rules of order and
     inclusion
   * there's one and only one 'self' at every point in the program
   * instance variables belong to 'self', always
   * class variables are completely unrelated to instance variables,
     in spite of the use of @ in one and @@ in the other
   * the def and class keywords start new local scopes
   * the class keyword can take either a constant (for a named class)
     or a "<< object" expression (for a singleton class)

I have to admit, I don't understand what this means in practical
terms. In fact I have a question I need to find an answer to, and I
want to post it in this thread, rather than as its own thing, in the
possibly idealistic hope that somebody can frame an answer in terms of
these principles, and help me understand them.

If they're not of practical value, then they're not of value. So I'll
give it a try :slight_smile:

Basically, I need to change a class method. It's the Ferret method
full_text_search, in a Rails app.

e.g.:

Thing.full_text_search("asdf")

I need to modify this class method. I tried alias, but did it wrong.

alias original_full_text_search full_text_search

but of course it doesn't work, because it's not an instance method but
a class method. Is this a good place for class_eval? I could be way
off.

Actually now that I re-read it, I think I do understand the basic
concepts, I think I'm just weak on the syntax.

In general, if you want to do:

   alias old_x x

you want to do so inside a class definition body for the class where x
is defined (or a subclass of that class).

A "class method" is basically a singleton method of a Class object.
That means that the class where it's defined is the singleton method
of that class object (because that's what singleton classes are: the
places where objects' singleton methods are defined).

In your case, the object in question is Thing. To get into a class
definition body for a singleton class, you use the class keyword plus
the "<< object" construct:

   class << Thing

You can now perform the aliasing:

     alias original_full_text_search full_text_search
     # redefinitions etc. will follow here

   end

Here's a complete mini-example:

class Thing
   def self.x
     puts "old x"
   end
end

class << Thing
   alias old_x x
   def x
     puts "new x..."
     old_x
   end
end

Thing.x

David

···

On Thu, 14 Dec 2006, Giles Bowkett wrote:

--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Ah, see what you mean now :slight_smile:

Martin DeMello wrote:

···

On 12/6/06, Tim Fletcher <twoggle@gmail.com> wrote:
> Logan Capaldo wrote:
> > >
> > If ruby were common lisp, that could actually work. But it's not and our
> > exceptions are not resuamble :).
>
> class Foo
> def bar
> yield
> rescue NameError => method_call
> p method_call.name
> end
> end
>
> Foo.new.bar { baz }

Breaks:

irb(main):008:0> a = Foo.new
=> #<Foo:0x2b301a826778>
irb(main):009:0> a.bar { baz }
:baz
=> nil
irb(main):010:0> a.bar { baz; quux }
:baz
=> nil

martin

Simple question, i come from a C/++ background and i'm just really starting to get "real things done with ruby" ( that should be a book title). Anyway as i start writing methods that return objects and variables and take objects and variables i've started to wonder how they actually get passed around. I haven't found a specific pointer or reference type construction, although since everything i've tried to do has worked i've not tried very hard.

I'm guessing that everything gets passed around by reference? Is that true? Also what about situations where you'd really want to use a pointer, like referring to huge things or ,god forbid, doing grimy things with arrays. It is very nice having all these things automated, like the garbage collection etc, but i still find myself wanting to free things. I've only just gotten over wanting to semi-colon every statement.

Probably by asking this i'm showing how i really haven't groked ruby at all. I'm happy to admit that.

Thanks