June 04, 2008 by alex
On a recent Rails project I had to use an old database schema that had been designed years ago for some php app. The two main entities in the application were companies and their projects. For whatever reason the designer had created one huge table called organizations with all the companies and projects inside. A row in the database marked a company when the is_company column was 1 and a project when the is_project column was 1.
|----------------------------------------------------| | id | name | is_company | is_project | |----------------------------------------------------| | 1 | google | 1 | 0 | | 2 | world domination | 0 | 1 | |----------------------------------------------------|
In my rails app I created two ActiveRecord models: Company and Project and set the table name for both to organizations:
Now the real problem was his: when I did a Company.find :all
I got all the companies and all the projects, so I had to do this instead: Company.find :all, :conditions => {:is_company => true}
- throughout the project, and whenever I forgot the condition somewhere all the projects showed up in the wrong place. So what I needed was a generic solution.
To make a longer story short I played with scope_out defining a projects
scope on the Company model, so I could at least do Company.find_all_companies
and didn’t have to specify the conditions over and over again - but that still wasn’t DRY at all. One morning short after waking up (the time I usually have the best ideas) it dawned on me how simple the solution actually is:
I added a scope around all find and count calls of my model and now I can just do whatever find operations I want and don’t have to think about scopes and tables ever again. Sweet object encapsulation.