I don’t really understand why people use namespaced models. I see ActiveRecord models as DSL for database. There is no concept of namespacing in Database, then why should you have them with models ? Apart from that, they are very buggy too !
“I am generally not a huge fan of namespaces for models. As I don’t think that’s a good fit for splitting up your domain.” - DHH
From what I’ve seen, the most common explanations given are :
- To organize models
- To reuse the code
Now let’s look at elegant solutions for both these problems.
For the purpose of this article, let’s assume you have models for different kind of pets. e.g. Dog, Cat & Rabbit.
How to organize models ?
Rails by default, wants you to put all your models in RAILS_ROOT/app/models directory. But that’s a convention. There is absolutely nothing that stops you from putting your model files anywhere you wish and organize them according to your liking and based on application specific logical groups.
1 2 3 4 5 |
Rails::Initializer.run do |config| # Your existing stuff config.load_paths << "#{RAILS_ROOT}/app/models/pets" end |
That’s it ! Now you can have dog.rb, cat.rb & rabbit.rb inside RAILS_ROOT/app/models/pets directory.
But what about reuse !?
Two ways to skin this cat :
- Good ol’ mixins
- Abstract models
Abstract models are the models which cannot have objects ( cannot be instantiated ) and hence they don’t have associated table as well. Every rails developer uses abstract model in their code without knowing it. ActiveRecord::Base. In our case, we can have an abstract model called Pet for keeping the common behavior of all the pets. And our models would look something like :
# RAILS_ROOT/app/models/pets/pet.rb1 2 3 4 5 6 |
class Pet < ActiveRecord::Base self.abstract_class = true belongs_to :person validates_presence_of :name end |
1 2 3 4 5 |
class Dog < Pet def bark "baaw" end end |
That’s it. Dog will inherit all the methods/validations/associations from parent Pet model and so will all the other models who would inherit from Pet abstract model. Please note that this is not STI as we have set self.abstract_class = true in Pet.







Oh hey, that’s nice. Can’t think of any real-world uses of this, though, care to give any examples – if any? All my ideas involve STI, such as a hardcoded permission systems (
Admin < User), task states (Finished < Task) etc.leethal : In many cases STI might not be the right fit, because you might end up having totally useless columns in your base table, and probably you may never be accessing your base model objects directly in some other cases.
Let’s say, you have an Article model. And children model are BlogArticle and NewsPaperArticle. Here, STI may not be a right fit when,
I suggested to use abstract models for cases where people use namespaced models. And of course, abstract model can act as an interface as well.
Databases like Oracle and M$oft Sql Server allow an user to access one or more schema, which can be used like namespaces.
eg: Two schema Account and Product Account.Customers Account.Invoices Account.Invoice_Items Product.Products Product.Stock_Prices
Though I don’t believe that ActiveRecord would automagic support this.
Thanks, helpfull article ! I was just struggling with the “models in subdirectory” issue myself. I don’t need the base-model, it’s only for organization. One question though: I managed to do the same with the controllers so I get: pets/cats_controller – pets/dogs_controller – ... But I’m having difficulties with the views, I would like to have my views like this: views\pets\dogs\index.rhtml – views\pets\cats\index.rhtml – ... Probably something silly, but how do I point my actions in ‘dogs_controller’ to the dog-subdirectory in views ? (I’m getting the ‘template missing views/dogs/index.rhtml’ error with the default render option)
Stijn : Thanks for the comment. For doing the same with views, you’ll need to append the path to ActionController::Base.view_paths. You should find more information here or you can check the docs/source as well.
I’ve wondered about a way to inherit AR classes without triggering STI. I somehow missed abstract classes. Thanks for enlightening me!
I tried out this example. But I get an error saying “Table ‘eventplanner_development.events’ doesn’t exist” when I try to add a record to either Ceremony or Party table. I have an abstract class like: class Event < ActiveRecord::Base self.abstract_class = true belongs_to :user validates_presence_of :name end
and then my usual models like: class Ceremony < Event end
class Party < Event end
Am I missing something here?
oops..something went wrong with my earlier comment. Hope its readable.
Subbu : Well, you’re certainly missing something somewhere ! Restart the server ;-)
Without model namespaces, you have to think up (potentially counterintuitive) distinct names for every model in your application. For larger applications this really becomes a problem, especially when you also have to avoid all of the Ruby core classes that also live in the default namespace.
Tom : So my argument against that is, you’ll surely have an associated table name with the model. E.g. If your model is called Item::Dvd, you’ll have a table called item_dvds, then why can’t you call your model ItemDvd ?
I’ll just copy paste my comment from Mike’s blog
By that post about namespaced models, I just meant to point out invalid reasons why most of the people use them. There still might be some cases ( which I haven’t really come across yet, so don’t know about them ) where namespacing model might be a good choice.
You’re right, you could just fake the effect of namespaces by prefixing all your model names instead, but… Ruby has namespaces! It’s extra effort and overhead to do all that prefixing, and you shouldn’t have to fake it if the language supports it. It’s Rails that’s causing the problem, not the people who are trying to use a good language feature for its intended purpose.
I agree that namespaced models are a world of pain and probably not worth the hassle, and I pretty much agree that your suggested workarounds are the best way to go at the moment, but I also think that namespaces do have a genuine use (which is why Ruby provides them) and that fundamentally it’s a shame that Rails doesn’t pay proper attention to them.
Roll on 3.0! :-)
Definitely, rails sucks when it comes to namespaces … especially in handling Item::Dvd and ItemDvd, where both map to item_dvd … its ambiguous. Whereas, logical separation is required as one of my projects has more than 40 models and I have to divide them into logical groups for convenience.
@Pratik, using abstract class is a good technique for Pet {Dog, Cat, Rabbit} example, and it works because Dog, Cat and Rabbit are of type Pet. Its a solid alternative to STI.
But this will not work when, for example, a company would like to divide its tables into groups of HR, Finance, Sales, etc. and there is no inheritance involved. Such cases do require a namespace.
Also … I think @Tom has genuine arguments.
Pratik,
I’m trying to get my head around STI. I think I have a valid use for it. I want to have cusomers of type Corporate or Individual. Each customer type stores certain attributes pertinent to its type. Each Customer type would end up having its own slightly different views. However there are a number of operations i just want to do on customers. For example i want to show a list of customers with just their basic information. The rest of the system doesnt really care much more about the type. For example a customer can have many “cases”. The case doesnt really care much for the type of the customer. It just belongs to a customer irrespective of the type.
Sorry for being verbose. But i hope you get the gist. How to go about the best possible way in Rails?
Thanks mate!
We have a Rails project that requires communicating with two databases. The main data repository is a remote db over which we have no control and a local one with extended informtaion. The application we are building serves as glue between the two.
We’ve namespaced the models and put those relating to the remote database in the vendor plugins folder. Part of the reason was to allow portablilty of the code that deals with the remote database and make it avialable to other teams building different applications.
I’m developing a plugin right now that needs a model. In this case I think it would be handy to have good support for namespaced models so that I don’t have to worry about conflicts with models in the application my plugin gets installed to. Then I could still pick simple and intuitive model names in my plugin.
Since the namespaced model support seems to be a little flaky, right now my only viable options seems to be picking unusual names for the model, or making the developer generate the model and let him or her pick a name. Both options are OK, but I personally find them a little less elegant than a namespace.
The main reason I like namespaced models is because the reason Eric Evans put in his Domain-Driven book. And I am going to quote it below:
you sure your scope is complete in you opinion?
It’s more like black and white to me here, You either namespace controller and model or neither.
Why would you namespace just the models and not the controllers?
Plus, As soon you put a controller inside a namespace everything else at the model expects to be namespaced. so adding directories to the load_path doesn’t help.
I believe fully support for one nesting level might be a blessing for many,
I would love to know your opinion on namespacing both controllers and models, or neither.
Pratik,
I used your idea of grouping my similar models into subdirectories, simply for “cleanliness” as opposed to namespacing (which I agree is usually a bad idea for models as models would rarely overlap in name). Turns out that I had about 6 subdirectories of models (went a little hog-wild) so rather than write
six times, I DRY’d it up. Woo!
Dir.glob(”#{RAILS_ROOT}/app/models/*[^.rb]”).each{|dir| config.load_paths << dir }
Enjoy!
-Dan
P.S. I didn’t know about the abstract class, but I had a situation that would have been perfect for it… I ended up making it work using “set_table_name” for each child class, but I now see that “abstract_class” would be cleaner as its only set on the parent.
I would like to comment that it does not work if you have a namespace controller and you want to do something like.
Test model in file test.rb located in /app/models/test/test.rb
class Test < ActiveRecord::Base TEST = [‘test’, ‘tester’] end
class Test::TestsController < ApplicationController
end
It fails hard by saying: Expected /Users/johanbuts/Sites/quasus/pis/app/models/test/test.rb to define Test::Test. When i move the file test.rb back in /app/models all works fine.
And naturally i’ve put the following in my environment.rb:
config.load_paths += %W( #{RAILS_ROOT}/app/models/test )
So i think the solution only works if you don’t namepace controllers like Andres mentioned 2 posts above.
super bummer :( :( :(
You can namespace the models and controllers as long as they’re not put in subdirectories of the same name. So you could do:
app/models/test_models/ app/controllers/test/
and it should work fine.
Re: Buts Johan’s post of November 03, 2008 @ 02:16 PM Yes strange annoying stuff like this happens all the time with Rails when you try things that are not exactly like the demonstration apps.
Let’s face it, Rails is BRITTLE.
You could call it “opinionated” if you prefer, but the bottom line is that Rails does what it does so easily by just supporting one way to do things. That’s fine but it becomes a real time waster due to rotten documentation and a blurring between documentation and online opinion. There is a lot of high-astonishment-factor behaviour in Rails, like in Buts Johan’s example. Who would guess that adding namespaced controllers would change the interpretation of (previously non-namespaced) model files? Wouldn’t it just be more helpful to document something like…
“PUT ALL YOUR MODELS IN THE apps/models SUBDIRECTORY OR YOU WILL BE SORRY, MAYBE NOT NOW, BUT EVENTUALLY” ??
I think that is truly the best advice!