Once more unto the breach: private class methods

Found a lot of discussion of this, but it didn't seem to suggest a
solution to a common pattern. The below completely useless example is
modeled after a longer and more useful one in the Agile Web
Development with Rails book (2nd ed):

class Foo
    class << self
          private
          def staticHelperFunction
               12345
          end
    end
    public
    def initialize
         @var = self.class.staticHelperFunction
    end
end
Foo.new.var

Now, the above won't work, obviously. If I replace the direct call to
staticHelperFunction with instance_eval or send, it will work, but
that feels hackish. Is there an idiomatic Ruby way to handle this
sort of situation?

In case the goal isn't clear, I want instance (not singleton/class)
methods of a given class to have access to what are essentially helper
functions/subroutines (not other instance methods of the same class)
which are not generally accessible outside of that class.

Doable?

Hi --

Found a lot of discussion of this, but it didn't seem to suggest a
solution to a common pattern. The below completely useless example is
modeled after a longer and more useful one in the Agile Web
Development with Rails book (2nd ed):

class Foo
   class << self
         private
         def staticHelperFunction
              12345
         end
   end
   public
   def initialize
        @var = self.class.staticHelperFunction
   end
end
Foo.new.var

Now, the above won't work, obviously. If I replace the direct call to
staticHelperFunction with instance_eval or send, it will work,

Not until you write a 'var' instance method :slight_smile:

but that feels hackish. Is there an idiomatic Ruby way to handle
this sort of situation?

In case the goal isn't clear, I want instance (not singleton/class)
methods of a given class to have access to what are essentially helper
functions/subroutines (not other instance methods of the same class)
which are not generally accessible outside of that class.

It seems like you're threading a very narrow needle. Do you mean that
you would not want class methods to see each other?

   class C
     def self.x # assume this is the kind of method you mean
     end

     def self.y
       x # This would fail?
     end
   end

That's a pretty tall order: having methods from which you can't call
other singleton methods of the very same object. Or am I
misunderstanding?

David

···

On Fri, 24 Aug 2007, Zeekar wrote:

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Found a lot of discussion of this, but it didn't seem to suggest a
solution to a common pattern. The below completely useless example is
modeled after a longer and more useful one in the Agile Web
Development with Rails book (2nd ed):

class Foo
    class << self
          private
          def staticHelperFunction
               12345
          end
    end
    public
    def initialize
         @var = self.class.staticHelperFunction
    end
end
Foo.new.var

Now, the above won't work, obviously. If I replace the direct call to
staticHelperFunction with instance_eval or send, it will work, but
that feels hackish. Is there an idiomatic Ruby way to handle this
sort of situation?

In case the goal isn't clear, I want instance (not singleton/class)
methods of a given class to have access to what are essentially helper
functions/subroutines (not other instance methods of the same class)
which are not generally accessible outside of that class.

Doable?

Sure, but clumsy, I do not know if it is worth it

class Foo
  class << self
    private
    def x; 60 end
  end
  attr_reader :x
  helper = method(:x)
  define_method :initialize do @x = helper.call end
end

puts Foo.new.x

HTH
Robert

···

On 8/23/07, Zeekar <markjreed@gmail.com> wrote:

--
I'm an atheist and that's it. I believe there's nothing we can know
except that we should be kind to each other and do what we can for
other people.
-- Katharine Hepburn

easy:

cfp:~ > cat a.rb
class C
   singleton_class =
     class << self
       self
     end

   helper = Object.new.instance_eval do
     def foo() 42 end
     self
   end

   [self, singleton_class].each do |c|
     c.module_eval{
       define_method(:helper){ helper }
       private :helper
     }
   end

   def initialize
     @foo = helper.foo
   end
end

p C.new
C.helper

cfp:~ > ruby a.rb
#<C:0x24b94 @foo=42>
a.rb:25: private method `helper' called for C:Class (NoMethodError)

but in the presence of both instance_eval, eval, and send - why bother?

a @ http://drawohara.com/

···

On Aug 23, 2007, at 2:10 PM, Zeekar wrote:

In case the goal isn't clear, I want instance (not singleton/class)
methods of a given class to have access to what are essentially helper
functions/subroutines (not other instance methods of the same class)
which are not generally accessible outside of that class.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

Not at all. I want to define a method C.foo() that other classes
outside of C can't call directly. Other class methods of C can call
it, fine. But the goal is to have *instances* of C to be able to call
it.

I guess I could make it a private instance method that just happens
not to care about self., but that seems like misleading design.

···

On Aug 23, 5:02 pm, "David A. Black" <dbl...@rubypal.com> wrote:

It seems like you're threading a very narrow needle. Do you mean that
you would not want class methods to see each other?

Well, that is an interesting approach. Thanks! It might be in the
same category as using instance_eval or send, but at first blush it
feels somewhat cleaner to me...

···

On Aug 23, 5:11 pm, "Robert Dober" <robert.do...@gmail.com> wrote:

Sure, but clumsy, I do not know if it is worth it

class Foo
  class << self
    private
    def x; 60 end
  end
  attr_reader :x
  helper = method(:x)
  define_method :initialize do @x = helper.call end
end

Hi --

It seems like you're threading a very narrow needle. Do you mean that
you would not want class methods to see each other?

Not at all. I want to define a method C.foo() that other classes
outside of C can't call directly. Other class methods of C can call
it, fine. But the goal is to have *instances* of C to be able to call
it.

OK -- I didn't get that; there was something to the effect that you
wanted instance methods, but not singleton or class methods, to be
able to call these methods, which is what confused me.

I guess I could make it a private instance method that just happens
not to care about self., but that seems like misleading design.

The code I came up with is similar to Ara's, except that I didn't make
the instance method version private which I believe probably does make
sense.

David

···

On Fri, 24 Aug 2007, Zeekar wrote:

On Aug 23, 5:02 pm, "David A. Black" <dbl...@rubypal.com> wrote:

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Without seeing the code you're actually working with, it seems to me
that I'd much rather see the method implemented as a private instance
method than as a class method (assuming that the purpose is to serve
as a utility method for use inside instances of the class).

I'm not sure why that would be considered misleading, and it would be /
much/ easier to follow the code than if you try to use some of the
other solutions offered. Not that the code suggested is /bad/, it's
just overkill for what you seem to be trying to accomplish, IMO.

···

On Aug 23, 2:20 pm, Zeekar <markjr...@gmail.com> wrote:

I want to define a method C.foo() that other classes
outside of C can't call directly. Other class methods of C can call
it, fine. But the goal is to have *instances* of C to be able to call
it.

I guess I could make it a private instance method that just happens
not to care about self., but that seems like misleading design.

--
Regards,

John Wilger