Singleton methods examples in book 0f ruby

I am a new rubier, so i learned ruby from book-of-ruby. I'm confused in the singleton methods example as below:

class Box
     def initialize( aStr )
         @msg = aStr
     end

     def look_inside
         puts( @msg )
     end
end

starprize = Box.new( "Star Prize" )
# create a singleton method
def starprize.congratulate
     puts( "You've won a fabulous holiday in Grimsby!" )
end

boxes = [Box.new("box1 is empty"),
          Box.new("box2 is empty"),
          starprize,
          Box.new("box3 is empty")]

boxes.each do |item|
     item.look_inside
     # test if the congratulate singleton method exists before calling it
     if item.singleton_methods.include?("congratulate") then
# if item.respond_to?( :congratulate ) then # an alternative test
         item.congratulate
     end
end

The question is if use "item.singleton_methods.include?("congratulate")" to evaluate, "item.congratulate" will never run as expected, why? In the same time, "item.respond_to?( :congratulate )" works well then.

#include? needs to be passed a symbol rather than a string, it doesn't
perform type conversion, so item.singleton_methods has :congratulate in and
you're checking for 'congratulate' which looks the same but as far as
Ruby's concerned is something pretty different.

Basically this should work:

if item.singleton_methods.include?(:congratulate)
  item.congratulate
end

Rhys

···

On 10 September 2014 15:11, xiaopeng <1093218247@qq.com> wrote:

I am a new rubier, so i learned ruby from book-of-ruby. I'm confused in
the singleton methods example as below:

class Box
    def initialize( aStr )
        @msg = aStr
    end

    def look_inside
        puts( @msg )
    end
end

starprize = Box.new( "Star Prize" )
# create a singleton method
def starprize.congratulate
    puts( "You've won a fabulous holiday in Grimsby!" )
end

boxes = [Box.new("box1 is empty"),
         Box.new("box2 is empty"),
         starprize,
         Box.new("box3 is empty")]

boxes.each do |item|
    item.look_inside
    # test if the congratulate singleton method exists before calling it
    if item.singleton_methods.include?("congratulate") then
# if item.respond_to?( :congratulate ) then # an alternative test
        item.congratulate
    end
end

The question is if use "item.singleton_methods.include?("congratulate")"
to evaluate, "item.congratulate" will never run as expected, why? In the
same time, "item.respond_to?( :congratulate )" works well then.

Yes, IIRC one of the changes between Ruby 1.8 and 1.9 was that lots of
methods that formerly returned strings now returned symbols.

And for the record, if a collection of objects ever doesn't contain
something you thought it should, you can always print out the
collection to see what it *does* contain. E.g.

    p starbox.singleton_methods

···

On 11/09/2014, Rhys Stansfield <r.stansfield@voc-8.com> wrote:

#include? needs to be passed a symbol rather than a string, it doesn't
perform type conversion, so item.singleton_methods has :congratulate in and
you're checking for 'congratulate' which looks the same but as far as
Ruby's concerned is something pretty different.

--
  Matthew Kerwin
  http://matthew.kerwin.net.au/

Hi,Matthew and Rhys, thanks for your solution and suggestion, it's well done now.

···

On 2014年09月11日 04:55, Matthew Kerwin wrote:

On 11/09/2014, Rhys Stansfield <r.stansfield@voc-8.com> wrote:

#include? needs to be passed a symbol rather than a string, it doesn't
perform type conversion, so item.singleton_methods has :congratulate in and
you're checking for 'congratulate' which looks the same but as far as
Ruby's concerned is something pretty different.

Yes, IIRC one of the changes between Ruby 1.8 and 1.9 was that lots of
methods that formerly returned strings now returned symbols.

And for the record, if a collection of objects ever doesn't contain
something you thought it should, you can always print out the
collection to see what it *does* contain. E.g.

     p starbox.singleton_methods