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 def self.columns() @columns ||= []; end 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.

[...] week I wrote about Tableless models in Ruby on Rails, giving an example of Recommendation model which could be used to validate users’ [...]
code tunes » Blog Archive » “Send this page to friend” with polymorphic controller in Rails
26 Jul 08 at 16:06
Why not use:
attr_accessor : recommendable_type, : recommendable_id, : email, : body
and continue on with your validations. I’ve been using ‘attr_accessor’ with all the advantages you list above. Is there a difference?
Karl Smith
26 Jul 08 at 23:11
By defining columns you can specify their types. That is useful when you use multiparameter attributes (like Date or DateTime types).
So there would be no difference in presented example, but if I added some Date field to the model, attr_accessor wouldn’t work well.
Michał Szajbe
27 Jul 08 at 16:22