Can someone explain me why Rails does not take full advantage of
namespaces? Rails itself is divided into modules but user classes are
restricted to use only names that don't coincide with existing class
names with is annoying. "Transaction", for example, is a reserved
name. But I find it ugly to use a name other than "Transaction" for
models that really ARE "Transactions".
Simple answer is that Ruby does not use a package system like you will
find in Java. This is just something you will have to live with and
learn to work around. Even in Java a "package" is really nothing more
that a way of "prefixing" class names. So you just need to devise
your own way of prefixing your class name, or simply take note of the
reserved names in Ruby and in Rails and avoid them.
As a long time Java user. I actually don't really miss the whole
packaging system imposed by Java. Especially after they added the
ridiculous restriction that you cannot access objects in the "default"
namespace from a class that is in a package. Now that I've been
developing in Cocoa and Ruby, I have come to appreciate the simplicity
of having no "packaging" system. It is no longer practical to ignore
the packaging system in Java, due my previously stated restriction.
I look at it this way, when defining a Java class that is in package
"com.mycompany" named "Transaction" the "real" class name is
com.mycompany.Transaction. I would personally prefer just
understanding that "Transaction" is a database transaction class used
by Rails and would instead name my class something more descriptive
like "AccountTransaction"
In any case this issue could cause a "flame war" about the
practicality of package systems. That is not my intention here.
You're going to find people on both sides of that fence. I happened
to have found a way to jump from the Java side of the fence, to the
Objective-C (Cocoa) and Ruby side of the fence.
Cocoa addresses this problem by convention. If you are creating a
framework that you expect to use in your other, then the classes
contained in the framework get prefixed with two capital letters.
This provides some protection from naming conflicts without adding the
complexity of a full packaging system. Some examples would be
NSArray, NSDictionary, CIImage, etc. Where NS stands for Next Step
(the operating system from which this core framework was extracted),
and CI stands for Core Image (another Cocoa framework).
Ruby uses a packaging system that uses modules instead of name
prefices like Java. And Rails does put different sets of logic into
separate modules. I just don't see why user code should not be in a
module of its own. I don't want to prefix all my models, and prefixing
just one seems inconsistent. Are there any "official" articles about
this topic?
While I agree the NS, CF, etc convention in Obj-C is the de-facto
solution for the non-namespaced nature of C in general, it is limited
since NS could just as easily be used by the the company Neanderthal
Solutions. This then forces longer abbreviation prefixes for
disambiguation. With Java, the nice thing about packages is that you
can refer to a class by its name if there is no ambiguity.
Otherwise, you provide the fully qualified name (including package).
Without namespacing, your class names are much longer. I think the
OP is really looking for a solution like modules. For instance, in
Ruby, it's perfectly legal to create a class named Bar inside the
module named Foo. It would be written as:
class Foo::Bar
end
Then if we needed a Bar for drinking, we could create another class/
module:
class Drinking::Bar
end
Each 'Bar' in that case is namespaced, providing context. This is
fundamentally similar to packaging in Java, with the added benefit
that modules can also act like Categories in Objective-C by adding in
methods.
The problem as the original poster brought up is that Rails doesn't
seem to really support this well for apps built with it (it certainly
uses it internally). There are certain benefits to the namespacing,
in addition to the distinct but identical class names it allows
providing context, you can then put classes inside subfolders
easily. ObjC doesn't really care where the files live in folder
structures, since you simply set the source folders in your compile
settings. However, Rails convention over configuration could be a
beautiful solution if it provided better support.
Viewing a rails app with lots of classes quickly becomes overwhelming
in Textmate, since there isn't any organization below the models
folder. XCode solves this with ObjC because you can create
artificial "groups" to organize your classes (both .h & .m) without
having to adjust compile settings, or use real folders with settings
changes.
Solutions. This then forces longer abbreviation prefixes for
disambiguation. With Java, the nice thing about packages is that you
can refer to a class by its name if there is no ambiguity.
Otherwise, you provide the fully qualified name (including package).
Yes, Ruby module namespaces work the same way.
The problem as the original poster brought up is that Rails doesn't
seem to really support this well for apps built with it (it certainly
uses it internally). There are certain benefits to the namespacing,
With respect, I would disagree. Rails 1.2 has full support for
namespaces at the model-view-controller level. You can even move your
whole app/ directory into a plugin. For migrations, you can have
plugins with different migration streams using PluginAWeek's excellent
plugin_migrations.
Viewing a rails app with lots of classes quickly becomes overwhelming
in Textmate, since there isn't any organization below the models
folder. XCode solves this with ObjC because you can create
Using Rails plugins, plus module namespaces, plus plugin_migrations
lets you organise your site into distinct segments of functionality --
they call it "vertical application slices" I believe.
Have a look at Goldberg for example. It's a full web application
framework with its own models, views, controllers, migrations and even
routes in RAILS_ROOT/vendor/plugins/goldberg/. And all its classes
are namespaced with "Goldberg::" so they don't conflict with any of
your own classes.