#445 new
Harri Kauhanen

Improved support for model namespaces (fixtures, generators, table naming)

Reported by Harri Kauhanen | June 18th, 2008 @ 10:09 AM

Rails 2.1 already has quite good support for namespaced models, and Edge Rails seems to fix some bugs left. In practice, however, there are still some issues left.

I really wanted to get namespaces and models work nicely. So here's a patch that changes one convention and improves Rails support for namespaced models. I never done such thingie before, so pardon any mistakes I made, but I surely found this screencast very useful. The patch is against the latest development trunk (18th June 2008).

The convention for database table names of namespaced models currently is:

  module Animal; class Lion < ActiveRecord::Base; end; end;
  Animal::Lion  # ( database name --> )  lions

I changed this to:

  Animal::Lion  # -->  animal_lions

This, however, overlaps with the convention of nested classes:

  class Animal < ActiveRecord::Base; class Lion < ActiveRecord::Base; end; end;  
  Animal::Lion  # -->  animal_lions

In practice, this is not such a big problem, because we now at least "bigger" namespace we can use, and I guess you will have problems anyways if you have a module and class with exactly same name in your Ruby code. I also tried convention of using two ugly underscores (e.g. animal__lions) and also tried to stick with the old convention. After all the experimenting, the convention I chose seemed to work best. The greatest benefit, of course, is that we really get bigger namespace for our models. It also improves how we can handle fixtures.

Perhaps the correct solution would be to provide this new table naming convention as configurable option?

I did quite a lot of manual testing using various associations. I also tried STI and polymorphic inheritance. They seemed to work well. has_many :through had problems, but it probably is an another problem (ticket #323 may contain a patch).

Next, I needed to check out the ActiveRecord tests pass. Well, they did not, because I changed the database table naming convention. Not many changes though, but one line did not please my very much:

  assert_equal 'my_application_business_company_my_application_business_client_contacts', MyApplication::Business::Client::Contact.table_name,  'table_name for ActiveRecord model enclosed by another ActiveRecord model'

MyApplication::Business::Client::Contact is inner class of MyApplication::Business::Company, so according the new rules, it is correct, but err... ugly. The positive aspect is that it gave as unlikely conflicting table name and probably it does not happen too often.

ActiveRecord tests depend of fixtures, and of course, they weren't working after the changes made. I really wanted fixtures to work so that I can organize fixtures just like I would organize my model files. For instance: 'animal' folder would contain 'lions.yml' for fixtures. The final solution, while being somewhat hackish, would find lion fixtures both under animal/lions.yml or animal_lions.yml. First one will keep you more organized and the latter one is consistent with the database table names.

Ok, all the existing tests pass and cannot find anything major by testing with Rails code and console. But what about generators? We use them every day and without working generators we don't really have working namespaces. These generator should now work fine by supporting namespaces:

  • model
  • resource
  • scaffold

For instance scaffolding an Animal::Lion should generate fully working controllers, views, routing, fixtures and test cases. The trickiest part was to improve routing, but now routes to namespaced resources should be namespaced as well. For instance:

  map.namespace :animal do |animal|
    animal.resources :lions
  end

I am still very much novice with my Rails abilities, and my code may still look more like Java than Ruby. Don't let this you down. Instead, please help me by testing the patch and by:

  • improving the code
  • writing some proper unit tests
  • check out if I have done something really stupid (yes, it's possible, see the comments in the patch)
  • giving those +1's :-)
  • tell me what should I do next

Comments and changes to this ticket

  • acechase

    acechase June 18th, 2008 @ 08:22 PM

    Hallelujah, how have we gone this long without model namespacing?!?!

    The big problem I see with your current approach is that it only works in one direction, from class name to table name.

    "Animal::Lion".tableize # --> animal_lions

    "animal_lions".classify # --> AnimalLion

    Until both directions work, I don't think module namespacing will be all that useful. It seems like we need some type of indicator to allow for translation in the other direction. Like you, I considered using a double underscore, but because that would require changes to Inflector#classify I opted instead for a double colon in my actual table name. Colon is a legal character in MySQL but I'm not sure about other dbs.

  • Harri Kauhanen

    Harri Kauhanen August 27th, 2008 @ 04:31 AM

      • → Tag changed from “” to “activerecord enhancement fixtures generators patch railties routing”

Please Login or create a free account to add a new comment.

You can update this ticket by sending an email to from your email client. (help)

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

Source available from github

The Git repository resides at http://github.com/rails

Check out the current development trunk (Edge Rails) with:

git clone git://github.com/rails/rails.git

The latest development for the 1.2.x and 2.0.x releases are on the 1-2-stable and 2-0-stable branches.

Creating a bug report

When creating a bug report, be sure to include as much relevant information as possible. Post the code sample that causes the problem. Preferably, alter the unit tests and show through either changed or added tests how the expected behavior is not occuring.

Security vulnerabilities should be reported via an email to security@rubyonrails.org, do not use trac for reporting security vulnerabilities. All content in trac is publicly available as soon as it is posted.

Then don't get your hopes up. Unless you have a "Code Red, Mission Critical, The World is Coming to an End" kinda bug, you're creating this ticket in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the ticket automatically will see any activity or that others will jump to fix it. Creating a ticket like this is mostly to help yourself start on the path of fixing the problem and for others to sign on to with a "I'm having this problem too".

Shared Ticket Bins