Inserting

Hi,
Let's say I have a third party module, Foo, with class Foo::Bar. I
have two classes, A and B, which inherit from Foo::Bar. And, I have a
set of class methods which need to be available to objects of class A
and B, and have access to all the class variables and methods from
Foo::Bar.

What is the best way to incorporate the needed methods into this
hierarchy? Right now I've just hacked them into the source for the
third party lib that I'm working with, after trying various options
such as reopening Foo::Bar in A (this obviously broke when I needed to
add class B), inserting another class into the hierarchy between Bar
and A and B, and probably some other ideas I've forgotten.

I know there is probably a simple solution to this but my OOP muscles
don't seem to be flexing optimally. Can anyone give me a nudge in the
right direction?

thanks
jh

···

--
James Hughes
Web application developer
Centre for Health Services and Policy Research
Vancouver, BC

Is it something like this you want?

# initial definitions
class A < Foo::Bar
   # ...
end

class B < Foo::Bar
   # ...
end

module ExtraMethods
   # ...
end

# extend initial definitions
class A
   include ExtraMethods
end

class B
   include ExtraMethods
end

Hi,
Let's say I have a third party module, Foo, with class Foo::Bar. I
have two classes, A and B, which inherit from Foo::Bar. And, I have a
set of class methods which need to be available to objects of class A
and B, and have access to all the class variables and methods from
Foo::Bar.

What is the best way to incorporate the needed methods into this
hierarchy? Right now I've just hacked them into the source for the
third party lib that I'm working with, after trying various options
such as reopening Foo::Bar in A (this obviously broke when I needed to

I don't understand why this would "obviously break" or what you mean by
"in A". If you reopen Foo::Bar, and both A and B inherit from Foo::Bar,
then modifications to Foo::Bar available to A should be available to B
as well.

add class B), inserting another class into the hierarchy between Bar
and A and B, and probably some other ideas I've forgotten.

I know there is probably a simple solution to this but my OOP muscles
don't seem to be flexing optimally. Can anyone give me a nudge in the
right direction?

You can also create a mixin and extend Foo::Bar with the mixin. If you
do this, instance methods in the mixin will be available as class
methods in Foo::Bar and derived classes.

Paul

···

On Fri, Jan 20, 2006 at 02:48:08AM +0900, James Hughes wrote:

Ok, I'm doing something like the following:

module FooBarHelper

  class << Foo::Bar
     # some instance methods, which reference class vars from Foo::Bar
  end
end

Then, in classes A and B I do "include FooBarHelper". When I run this
I get "uninitialized class variable" errors for the Foo::Bar's class
vars.

So, to state my question again, how can I extend the functionality of
the Foo::Bar library (short of hacking it's source directly), while
still maintaining access to the class variables defined in Foo::Bar?
Is this even possible?

jh

jh

···

On 1/19/06, Paul Brannan <pbrannan@atdesk.com> wrote:

You can also create a mixin and extend Foo::Bar with the mixin. If you
do this, instance methods in the mixin will be available as class
methods in Foo::Bar and derived classes.

--
James Hughes
Web application developer
Centre for Health Services and Policy Research
Vancouver, BC

Hi --

You can also create a mixin and extend Foo::Bar with the mixin. If you
do this, instance methods in the mixin will be available as class
methods in Foo::Bar and derived classes.

Ok, I'm doing something like the following:

module FooBarHelper

class << Foo::Bar
    # some instance methods, which reference class vars from Foo::Bar
end
end

Then, in classes A and B I do "include FooBarHelper". When I run this
I get "uninitialized class variable" errors for the Foo::Bar's class
vars.

So, to state my question again, how can I extend the functionality of
the Foo::Bar library (short of hacking it's source directly), while
still maintaining access to the class variables defined in Foo::Bar?
Is this even possible?

Does this help at all?

   module Foo
     class Bar
       def self.meth
         puts "Class method of Foo::Bar"
       end
       X = "Constant of Foo::Bar"
     end
   end

   module Needed
     def self.const_missing(c)
       Foo::Bar.const_get(c)
     end
     def needed_method
       puts "This is a needed method"
       puts X
     end
   end

   class A < Foo::Bar
     extend Needed
   end

   puts A::X
   A.meth
   A.needed_method

David

···

On Sat, 21 Jan 2006, James Hughes wrote:

On 1/19/06, Paul Brannan <pbrannan@atdesk.com> wrote:

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!

Hmm. Not sure yet. While I try to wrap my head around what's going on
with the const_missing and const_get magic above, here is the short
script I wrote to try and simulate the real-world problem I'm trying
to solve. Note that the derived class (A) is trying to access a class
variable and not a constant as in your example.

module Foo
  class Bar
    @@classvar = "Boo!"
  end
end

module FooBarHelper
  class << Foo::Bar
    def amethod
      puts @@classvar
    end
  end
end

class A < Foo::Bar
  include FooBarHelper
  extend FooBarHelper
end

A.amethod

**end script**

This prints
./foo.rb:12:in `amethod': uninitialized class variable @@classvar in
FooBarHelper (NameError)
  from ./foo.rb:22

···

On 1/20/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

Hi --

On Sat, 21 Jan 2006, James Hughes wrote:

> On 1/19/06, Paul Brannan <pbrannan@atdesk.com> wrote:
>>
>> You can also create a mixin and extend Foo::Bar with the mixin. If you
>> do this, instance methods in the mixin will be available as class
>> methods in Foo::Bar and derived classes.
>
> Ok, I'm doing something like the following:
>
> module FooBarHelper
>
> class << Foo::Bar
> # some instance methods, which reference class vars from Foo::Bar
> end
> end
>
> Then, in classes A and B I do "include FooBarHelper". When I run this
> I get "uninitialized class variable" errors for the Foo::Bar's class
> vars.
>
> So, to state my question again, how can I extend the functionality of
> the Foo::Bar library (short of hacking it's source directly), while
> still maintaining access to the class variables defined in Foo::Bar?
> Is this even possible?

Does this help at all?

   module Foo
     class Bar
       def self.meth
         puts "Class method of Foo::Bar"
       end
       X = "Constant of Foo::Bar"
     end
   end

   module Needed
     def self.const_missing(c)
       Foo::Bar.const_get(c)
     end
     def needed_method
       puts "This is a needed method"
       puts X
     end
   end

   class A < Foo::Bar
     extend Needed
   end

   puts A::X
   A.meth
   A.needed_method

--
James Hughes
Web application developer
Centre for Health Services and Policy Research
Vancouver, BC

Hi --

Hi --

You can also create a mixin and extend Foo::Bar with the mixin. If you
do this, instance methods in the mixin will be available as class
methods in Foo::Bar and derived classes.

Ok, I'm doing something like the following:

module FooBarHelper

class << Foo::Bar
    # some instance methods, which reference class vars from Foo::Bar
end
end

Then, in classes A and B I do "include FooBarHelper". When I run this
I get "uninitialized class variable" errors for the Foo::Bar's class
vars.

So, to state my question again, how can I extend the functionality of
the Foo::Bar library (short of hacking it's source directly), while
still maintaining access to the class variables defined in Foo::Bar?
Is this even possible?

Does this help at all?

[...]

Hmm. Not sure yet. While I try to wrap my head around what's going on
with the const_missing and const_get magic above, here is the short
script I wrote to try and simulate the real-world problem I'm trying
to solve. Note that the derived class (A) is trying to access a class
variable and not a constant as in your example.

Whoops, I misread.

module Foo
class Bar
   @@classvar = "Boo!"
end
end

module FooBarHelper
class << Foo::Bar
   def amethod
     puts @@classvar

The class variables of Foo::Bar's singleton class are not the same as
those of Foo::Bar, so you'd want to avoid opening up the singleton
class. You can do this instead:

class Foo::Bar
   def self.amethod
     puts @@classvar
   end
end

As things stand there's no need for the FooBarHelper module at all:

class A < Foo::Bar
end

A.amethod # Boo!

David

···

On Sat, 21 Jan 2006, James Hughes wrote:

On 1/20/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

On Sat, 21 Jan 2006, James Hughes wrote:

On 1/19/06, Paul Brannan <pbrannan@atdesk.com> wrote:

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!

>> Does this help at all?

[...]

> Hmm. Not sure yet. While I try to wrap my head around what's going on
> with the const_missing and const_get magic above, here is the short
> script I wrote to try and simulate the real-world problem I'm trying
> to solve. Note that the derived class (A) is trying to access a class
> variable and not a constant as in your example.

Whoops, I misread.

> module Foo
> class Bar
> @@classvar = "Boo!"
> end
> end
>
> module FooBarHelper
> class << Foo::Bar
> def amethod
> puts @@classvar

The class variables of Foo::Bar's singleton class are not the same as
those of Foo::Bar, so you'd want to avoid opening up the singleton
class.

Ah, is that what I'm doing? :wink: Must reread the pickaxe chapters on
Ruby's object system...

You can do this instead:

class Foo::Bar
   def self.amethod
     puts @@classvar
   end
end

Right. This was my interim solution. However, as mentioned previously
in this thread, Foo::Bar is a third party gem (the ActiveLDAP module,
just to add some context to all this), and I want to avoid having to
maintain my additions to this everytime the lib gets a new release.

As things stand there's no need for the FooBarHelper module at all:

Yes, unless I'm trying to avoid directly modifying a third party
module as outlined above.
Just to add a bit more context to what I'm trying to achieve here, the
class variable I'm trying to access is a ruby-ldap connection object.
If my only option is to modify ActiveLDAP itself as you've suggested
here, then that's the way I'll go. Is that my only option? Thanks for
your responses so far.

jh

···

On 1/20/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

--
James Hughes
Web application developer
Centre for Health Services and Policy Research
Vancouver, BC

Hi --

>> Hi --
>>
>>
>>>>
>>>> You can also create a mixin and extend Foo::Bar with the mixin. If you
>>>> do this, instance methods in the mixin will be available as class
>>>> methods in Foo::Bar and derived classes.
>>>
>>> Ok, I'm doing something like the following:
>>>
>>> module FooBarHelper
>>>
>>> class << Foo::Bar
>>> # some instance methods, which reference class vars from Foo::Bar
>>> end
>>> end
>>>
>>> Then, in classes A and B I do "include FooBarHelper". When I run this
>>> I get "uninitialized class variable" errors for the Foo::Bar's class
>>> vars.
>>>
>>> So, to state my question again, how can I extend the functionality of
>>> the Foo::Bar library (short of hacking it's source directly), while
>>> still maintaining access to the class variables defined in Foo::Bar?
>>> Is this even possible?
>>
>> Does this help at all?

[...]

> Hmm. Not sure yet. While I try to wrap my head around what's going on
> with the const_missing and const_get magic above, here is the short
> script I wrote to try and simulate the real-world problem I'm trying
> to solve. Note that the derived class (A) is trying to access a class
> variable and not a constant as in your example.

Whoops, I misread.

> module Foo
> class Bar
> @@classvar = "Boo!"
> end
> end
>
> module FooBarHelper
> class << Foo::Bar
> def amethod
> puts @@classvar

The class variables of Foo::Bar's singleton class are not the same as
those of Foo::Bar, so you'd want to avoid opening up the singleton
class. You can do this instead:

class Foo::Bar
   def self.amethod
     puts @@classvar
   end
end

As things stand there's no need for the FooBarHelper module at all:

class A < Foo::Bar
end

A.amethod # Boo!

David

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!
Ruby for Rails

···

On 1/20/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

On Sat, 21 Jan 2006, James Hughes wrote:
> On 1/20/06, dblack@wobblini.net <dblack@wobblini.net> wrote:
>> On Sat, 21 Jan 2006, James Hughes wrote:
>>> On 1/19/06, Paul Brannan <pbrannan@atdesk.com> wrote:

--
James Hughes
Web application developer
Centre for Health Services and Policy Research
Vancouver, BC

(Sorry for that last bit of noise, itchy tab-key finger...)
So what I ended up with is I took advantage of the fact that my
third-party lib provides an accessor for the class variable I was
trying to get at. I use this in my helper module, which reopens the
class and which in turn is mixed in to my subclasses (A and B in the
contrived example) and all is well. Apologies to all for whom all this
was blindingly obvious. As it is for me, _now_.

jh

···

On 1/21/06, James Hughes <hughes.james@gmail.com> wrote:

On 1/20/06, dblack@wobblini.net <dblack@wobblini.net> wrote:
> >> Does this help at all?
>
> [...]
>
> > Hmm. Not sure yet. While I try to wrap my head around what's going on
> > with the const_missing and const_get magic above, here is the short
> > script I wrote to try and simulate the real-world problem I'm trying
> > to solve. Note that the derived class (A) is trying to access a class
> > variable and not a constant as in your example.
>
> Whoops, I misread.
>
> > module Foo
> > class Bar
> > @@classvar = "Boo!"
> > end
> > end
> >
> > module FooBarHelper
> > class << Foo::Bar
> > def amethod
> > puts @@classvar
>
> The class variables of Foo::Bar's singleton class are not the same as
> those of Foo::Bar, so you'd want to avoid opening up the singleton
> class.

Ah, is that what I'm doing? :wink: Must reread the pickaxe chapters on
Ruby's object system...

> You can do this instead:
>
> class Foo::Bar
> def self.amethod
> puts @@classvar
> end
> end

Right. This was my interim solution. However, as mentioned previously
in this thread, Foo::Bar is a third party gem (the ActiveLDAP module,
just to add some context to all this), and I want to avoid having to
maintain my additions to this everytime the lib gets a new release.

>
> As things stand there's no need for the FooBarHelper module at all:

Yes, unless I'm trying to avoid directly modifying a third party
module as outlined above.
Just to add a bit more context to what I'm trying to achieve here, the
class variable I'm trying to access is a ruby-ldap connection object.
If my only option is to modify ActiveLDAP itself as you've suggested
here, then that's the way I'll go. Is that my only option? Thanks for
your responses so far.

jh

--
James Hughes
Web application developer
Centre for Health Services and Policy Research
Vancouver, BC

--
James Hughes
Web application developer
Centre for Health Services and Policy Research
Vancouver, BC