Tableless models in Rails
If you’re developing an application in Ruby on Rails framework, there are many situations when you should consider using tableless models. The advantages you’d get are:
consistent application structure, because you’re using models to represent objects in your app
routes available for free if you also define controllers dedicated for those models, resulting in RESTful application
easy validation (just like with normal models) and other goodies shipped with Active Record
easier testing with unit tests
form building as easy as with normal models
If you’re familiar with “fat model, skinny controller” concept you’ll find more reasons.
An example situation: you give the users an ability to recommends object they find on the site to their friends. They can recommend photos and articles. You do not want to track those recommendations in database. Your model file would look like this.
class Recommendation < ActiveRecord::Base
class_inheritable_accessor :columns
self.columns = []
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
end
column :recommendable_type, :string
column :recommendable_id, :integer
column :email, :string
column :body, :text
belongs_to :recommendable, :polymorphic => true
validates_presence_of :recommendable
validates_associated :recommendable
validates_format_of :email, :with => /^$|^\S+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,4}|[0-9]{1,4})(\]?)$/ix
validates_presence_of :body
end
As you can see the only difference in model definition is that you need to provide the columns yourself.
The idea was borrowed from this snippet.
In the next article I’ll cover polymorphic controllers which will help to convert above example into complete one.
[edit: Thanks to Curran Schiefelbein for making this work when tableless model is inherited by another model.]
Comments