Namespacing question

3 views
Skip to first unread message

Marvin Humphrey

unread,
Jan 5, 2012, 10:06:05 AM1/5/12
to sdr...@googlegroups.com
Greets,

I'd like to release a gem foo-bar, which contains the classes
Foo::Bar::Stuff and Foo::Bar::Things. Is it possible to do this without
claiming the namespace "Foo"?

The motivation here is to release multiple *unrelated* gems under the same
top-level namespace. None of them should require a prerequisite 'foo'.

I'm having difficulty seeing how this would work because it doesn't seem to be
possible to create a class "Foo::Bar" unless a class or module named "Foo"
already exists. Thus, each gem would need to create "Foo", presumably
introducing a conflict if they are ever loaded within the same process.

Marvin Humphrey

Joe Fox

unread,
Jan 5, 2012, 10:22:19 AM1/5/12
to sdr...@googlegroups.com
Hi Marvin,

One of the interesting things about ruby is that you can effectively open up a class or module and add to it at any time. This is usually referred to as monkey patching. The only way there would be conflicts is if you had two modules defining the same function. Even in that case, you wouldn't get an error, you would just have the last module overwrite any prior modules. But as long as the modules define separate functions, or sub modules, you shouldn't have any problems.

-Joe Fox
codenoise.com

> --
> SD Ruby mailing list
> sdr...@googlegroups.com
> http://groups.google.com/group/sdruby

Ben Hughes

unread,
Jan 5, 2012, 12:36:02 PM1/5/12
to sdr...@googlegroups.com
Marvin,

It will work, just declare the module in Gem A:

module Foo
  module Bar
    class Stuff; end
  end
end

If another (Gem B) you can do the same thing:

module Foo
  module Bar
    class Things; end
  end
end

The key here is to declare the module explicitly like the above; you can't just do:

class Foo::Bar::Stuff
end

Because the reference Foo is not already defined.

Ben



Marvin Humphrey

Marvin Humphrey

unread,
Jan 5, 2012, 1:04:41 PM1/5/12
to sdr...@googlegroups.com
On Thu, Jan 05, 2012 at 05:36:02PM +0000, Ben Hughes wrote:
> It will work, just declare the module in Gem A:

> module Foo
> module Bar
> class Stuff; end
> end
> end
>
> If another (Gem B) you can do the same thing:
>
> module Foo
> module Bar
> class Things; end
> end
> end

Thanks. :) It looks like the only thing to worry about is whether someone else
goes and defines "Foo" as a class, since a namespace can only be either a
module or a class.

http://www.martinicity.net/articles/2006/07/15/ruby-namespace-conflicts

The other issue I had to resolve was whether the Ruby C API function
rb_define_module could be invoked more than once with the same module name.
Dunno if it's documented anywhere, but that's the behavior when I snoop the
source code in class.c:

if (rb_const_defined(rb_cObject, id)) {
module = rb_const_get(rb_cObject, id);
if (TYPE(module) == T_MODULE)
return module;
rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
}

(We're actually going to be creating a C extension.)

Marvin Humphrey

Robert Kaufman

unread,
Jan 5, 2012, 1:15:24 PM1/5/12
to sdr...@googlegroups.com
Also, as long as you have your code under Bar, only Bar is really polluted.  In the case of 

module Foo
  module Bar
    class Stuff; end
  end
end

If another (Gem B) you can do the same thing:

module Foo
  module Bazz
    class Things; end
  end
end

Foo::Bar is isolated from Foo::Bazz and you avoid the issues the Joe mentioned.

Best,
Rob

Peter Gumeson

unread,
Jan 5, 2012, 1:29:59 PM1/5/12
to sdr...@googlegroups.com
+1 for using the dash to represent modules correctly in your gem naming.

correct:

foo_bar =>  FooBar
foo-bar  =>  Foo::Bar
foo-bar_baz  =>  Foo::BarBaz

incorrect:

foo-bar => FooBar
 

Reply all
Reply to author
Forward
0 new messages