Forum: Ruby namespace instance methods?

Posted by Craayzie As a fox (craayzie)
on 2012-08-13 03:17
I have a large class with many instance methods that I want to
namespace:

object.namespace1.method_a
object.namespace1.method_b
object.namespace2.method_c
object.namespace2.method_d

How do I accomplish this? Of course I can always do this:

object.namespace1_method_a
object.namespace1_method_b

But I'm wondering if there's a better way.

Thanks in advance!
Posted by Jan E. (jacques1)
on 2012-08-13 07:23
Hi,

When the class is so large that you want to categorize the methods, it's 
definitely too large.

Split the big class into several smaller classes. The obvious approach 
would be to create a separate class for each of your "namespaces".
Posted by Craayzie As a fox (craayzie)
on 2012-08-13 09:34
Thanks for the quick reply. I guess what I really want is an object
within an object so I can still make calls like:

object.namespace1.method_a

in other words:

object1.object2.method_a

class Object1
  def object2
    Object2.new
  end
end

class Object2
  def method_a
  end
end

object1 = Object1.new
object1.object2.method_a

And that seems to work :) Thanks again for the help!!
Posted by Jan E. (jacques1)
on 2012-08-13 09:49
That does work, but it makes no sense, because you're creating a new 
object on every call.

The objects should be created in the initialize method and then saved in 
instance variables.
Posted by Craayzie As a fox (craayzie)
on 2012-08-13 10:09
Lol. Thank you :) looking forward to this journey
Posted by Brian Candler (candlerb)
on 2012-08-13 10:50
Jan E. wrote in post #1072166:
> The objects should be created in the initialize method and then saved in
> instance variables.

Or you can use a lazy initialize:

class Top
  class Facade1
    ...
  end
  class Facade2
    ...
  end
  def facade1
    @facade1 ||= Facade1.new(self)
  end
  def facade2
    @facade2 ||= Facade2.new(self)
  end
end
Posted by Chad Perrin (Guest)
on 2012-08-13 21:18
(Received via mailing list)
On Mon, Aug 13, 2012 at 04:35:00PM +0900, John Doe wrote:
>   def object2
> object1.object2.method_a
>
> And that seems to work :) Thanks again for the help!!

Why not use modules as namespaces?
Posted by Craayzie As a fox (craayzie)
on 2012-08-14 01:46
Brian Candler wrote in post #1072176:
> Or you can use a lazy initialize:

Very nice!

Chad Perrin wrote in post #1072243
> Why not use modules as namespaces?

I guess I don't know the difference between Classes vs. Modules when it
comes to namespacing?

My understanding is that you would use a Module if you intended to reuse
that class elsewhere.

In my case, class Object2 will only be referenced by class Object1 so I
think classes seem to work great?

I'm probably missing the obvious ;)
Posted by Jan E. (jacques1)
on 2012-08-14 10:18
John Doe wrote in post #1072269:
> My understanding is that you would use a Module if you intended to reuse
> that class elsewhere.

No, using modules as mixins for classes is only one purpose. You can 
also use them as namespaces or as collections of "functions" (like the 
Math module).

Modules are generally used as "static" collections, while classes are 
used to create instances. But there may be situations where both fit.
Posted by Robert Klemme (robert_k78)
on 2012-08-14 10:22
(Received via mailing list)
On Mon, Aug 13, 2012 at 9:17 PM, Chad Perrin <code@apotheon.net> wrote:

> Why not use modules as namespaces?

How would you use modules as namespaces here?  If the class includes
all those modules their methods are not in different namespaces but
all visible at the instance.

I agree with what Jan wrote: if the class is so large then there are
definitively too many methods and too few classes.  OP, can you please
show a realistic example or explain what you want to do?

Kind regards

robert
Posted by Craayzie As a fox (craayzie)
on 2012-08-14 18:08
Robert Klemme wrote in post #1072313:
> OP, can you please show a realistic example or explain what you want to do?

Thanks Robert - here's what I'm trying to do:

hostname = WebProperty.new 'www.yahoo.com'
hostname.DNS.lookup
hostname.HTTP.lookup

Where hostname, DNS and HTTP all have many of their own methods but 
there is a direct relationship between hostname + DNS and hostname + 
HTTP

Thanks!
Posted by Brian Candler (candlerb)
on 2012-08-14 21:46
John Doe wrote in post #1072359:
> hostname = WebProperty.new 'www.yahoo.com'
> hostname.DNS.lookup
> hostname.HTTP.lookup

HTTP doesn't have a "lookup" operation, so do you mean something like

hostname.HTTP.get('/index.html') ?

This is the typical OO conundrum. For a method which takes two object 
arguments, which class does the logic belong to?

If there is no polymorphism involved then it doesn't really matter, and 
in this case arguably it doesn't belong to either:

HTTP.get(hostname, '/index.html')

Or maybe the logic belongs in a URI object.

One advantage of your approach is that hostname.HTTP could keep track of 
a persistent HTTP connection, so that a series of hostname.HTTP.get() 
operations would re-use the same connection.

My natural inclination would be instead to have a "HTTP fetcher" class: 
this is not too dissimilar, but it makes it more obvious how to set 
options which are specific to the HTTP connection, rather than to the 
thing you're connecting to. (Timeouts, for example).

http1 = HTTP.new :hostname=>'www.google.com', 
:http_proxy=>"gw1.example.com"
http2 = HTTP.new :hostname=>'www.yahoo.com', 
:http_proxy=>"gw2.example.com"
yahoo = http1.get '/index.html'
google = http2.get '/index.html'

This approach is also arguably more pluggable.

But this is entirely subjective: hostname.HTTP.get(path) will obviously 
work, and if it makes sense for your particular application, then by all 
means use it.
Posted by Craayzie As a fox (craayzie)
on 2012-08-14 22:24
Brian, thank you for the taking the time to write such a complete 
response. It's reassuring to know that I'm on the right track.

Thanks again - really appreciate it.
Posted by Robert Klemme (robert_k78)
on 2012-08-15 09:04
(Received via mailing list)
On Tue, Aug 14, 2012 at 10:24 PM, John Doe <lists@ruby-forum.com> wrote:
> Brian, thank you for the taking the time to write such a complete
> response. It's reassuring to know that I'm on the right track.

I am not sure.  What is your motivation for having one object and
distributing methods across a number of other objects?  I am asking
because there is an anti pattern called "god object".  What you
describe has some similarities with that - but I can't say for sure
yet.

https://en.wikipedia.org/wiki/God_object
http://c2.com/cgi/wiki?GodObject
http://c2.com/cgi/wiki?GodClass

Kind regards

robert
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.