A Journey On Rails

Namespaced models and controllers

Posted in code organization, Rails by Vikram Venkatesan on January 27, 2010

Namespacing ruby classes using modules is one of the powerful features of ruby that is underused in rails. The problem is with using them in models and controllers since rails’ default conventions and configurations do not provide much support for namespaces. For instance, if you want a model for storing user settings separate from the basic user information (say, User model), you may create a model called UserSetting with an underlying table called user_settings. Here, the prefix User which we have used is nothing but the context in which the model works. A better approach in my opinion is to put the Profile and Setting models inside a namespace, say User, like User::Profile and User::Setting. That way, the redundancy in naming is solved. Now, coming to how rails supports this usage, the major areas where you may face problem are

Table naming

Rails defaults to the table name inferred from the class name of the model, excluding the namespace. So, it will assume settings to be the table name. You will have to call set_table_name to make it use user_settings, if required.

set_table_name 'user_settings'

Associations

The association class names and foreign keys will have to be specified explicitly.

belongs_to :user_setting,
           :class_name => 'User::Setting'
           :foreign_key => 'user_settings_id'

Fixtures

Name based fixture association references won’t work for namespaced models. Say, there is a belongs_to :user_profile in User::Setting model. In user_settings.yml you cannot directly use the fixture name like follows.

setting_one:
 user_profile: profile_one

You may have to use hard-coded ids and use the foreign key column name, like user_profile_id : 5. I struggled the most to get around this limitation since I could not change all my old fixtures to use hard coded id’s. Honestly, I do not know any better way to make this work and am still searching for it.

Update: Call set_fixture_class :user_settings => User::Setting to enable using named fixtures as given above.

There are many articles and blogs talking about the merits and demerits of using namespaces in rails so as to keep the code structured and clean. A few even recommend not using namespaces due the lack of good support for it.

But, from my experience with it, the advantages you get by using them overweigh it’s demerits. It’s about time rails starts supporting namespaces. You may find it hard to get it working for the first time. Once it’s into practice, you will not regret the choice.

3 Responses

Subscribe to comments with RSS.

  1. thoran said, on August 15, 2010 at 6:32 am

    In Associations, it should read, :class_name => User::Setting.

  2. jubbies said, on March 30, 2011 at 7:36 pm

    I was getting this error:
    NoMethodError: undefined method `match’ for

    And realized there needed to be quotes around User::Setting
    :class_name => ‘User::Setting’

    • Vikram Venkatesan said, on March 31, 2011 at 6:34 am

      Yes jubbies, it should be ‘User::Setting’. Thanks to thoran too, for spotting it.


Leave a comment