On Sat, Sep 18, 2010 at 12:09 PM, Emanuele Ianni <dierre / gmail.com> wrote:

> Colin Bartlett wrote:
> > puts "Date.day_fraction_to_time using wrapper"
> > class Date
> >     class << self
> >       def wrap_day_fraction_to_time( day_frac )
> >         day_fraction_to_time( day_frac )
> >       end
> >    end
> > end
> > hours, minutes, seconds, frac =
> >     Date.wrap_day_fraction_to_time( stop - start )
> > p hours, minutes, seconds, frac
>
> Thanks for the answer. Could you explain me the wrapper in detail,
> please? I'm assuming you're extending the Date class with an anonymous
>  class but it's really not clear to me the class << self declaration.

I'm not surprised that "class << self" isn't clear to you. It wasn't clear
to me when I first saw it, and I'm not sure I'm 100% there yet! I hope the
following is right and helps. (Corrections are welcome.)

Here's a link to the online first edition of Programming Ruby
http://ruby-doc.org/docs/ProgrammingRuby/html/classes.html
... Object-Specific Classes ...

Basically you can extend any object with methods which won't be available to
any other object unless you also extend that other object.

In the version of Date with Ruby 1.9 one way used is to set up an
(anonymous?) module and then use "extend", as shown in the extract from
(1.9) Date in my first post in this thread.

Another way is to use the "class << object" notation, which (I think) says
evaluate the code in "class<<...end" in the context of the specified object,
extending that object (as singleton methods of that object) with any methods
defined in "class<<...end". For example:
obj = Array.new
(r = obj.new_singleton_method) rescue p $! #=> undefined method error
class << obj
    def new_singleton_method(); "Karel Capek"; end
end
r = obj.new_singleton_method #=> "Karel Capek"

So in:
class Date
    class << self
      def wrap_day_fraction_to_time( day_frac )
        day_fraction_to_time( day_frac )
      end
    end
end
the object being extended in "class<<self...end" is whatever "self" is, and
in the context of the "class Date" self is the Date class. And the private
method "day_fraction_to_time" is accessible from "within" the object, so we
can write a public method (callable as Date.wrap_day_fraction_to_time) which
calls the private method "day_fraction_to_time".

Also, instead of writing a wrapper method, the following (simpler) way also
seems to work:
hours = mins = secs = nil
hours, mins, secs = Date.day_fraction_to_time( 0.03125 ) rescue p $!
p hours, mins, secs #=> nil, nil, nil
class Date
    class << self
      public :day_fraction_to_time
    end
end
hours, mins, secs = Date.day_fraction_to_time( 0.03125 ) rescue p $!
p hours, mins, secs #=> 0, 45, 0

In the context of a private method, I'm not at all sure that putting a
public wrapper method which calls it is better than simply making the
private method public: I think that any downsides/problems with making the
private method public will also apply to wrapping it. Does anyone know (or
think) differently?