Home Contact Sitemap

Preston Lee

Founder, CEO, OpenRain.com

About

During the day I run OpenRain in Phoenix: a Ruby on Rails development shop. During the night... well... I still have to run OpenRain, but when I find time to breathe, I exhale here. If you'd like to get in touch professionally, don't hesitate to contact me via the OpenRain website.

Peace,

Preston

Rails 2.0: Validations Without Extending ActiveRecord::Base

In more “enterprisey” web stacks (such as Java with Hibernate and Spring MVC), it’s straightforward to design a validatable form whose contents do not correspond directly — if at all — to a persistent OR/M class: such as may happen in an ecommerce site where you’re collecting payment information but can only store some of it in the database for legal reasons. Just create a MVC-level view object using your framework-specific validation mechanism, and translate to/from the relevant OR/M classes as necessary in the controller.

This scenario isn’t always straightforward to handle in Rails since the stack layers are smooshed together. In Rails 1.2.x, you could use (some) validations in your non-persistent PORO objects by extending ActiveRecord::Base and overriding the initializer to skip the databases-related stuff. Alas, this hack does not seem to work in Rails 2.0, but I have a solution which, in my brief testing, seems to work better than the aforementioned Rails 1.2 hack.

Here’s how I used ActiveRecord::Validations in one of my view-only classes in a Rails 2.0.2 application without needing a dummy table in the database or ActiveRecord::Base.


require 'active_record/validations'

class Card

# Define your arbitrary PORO attributes.
attr_accessor :number
attr_accessor :expiration_month
attr_accessor :expiration_year
attr_accessor :verification_value

# For the ActiveRecord::Errors object.
attr_accessor :errors

def initialize(opts = {})

# Create an Errors object, which is required by validations and to use some view methods.
@errors = ActiveRecord::Errors.new(self)

end

# Dummy stub to make validtions happy.
def save
end

# Dummy stub to make validtions happy.
def save!
end

# Dummy stub to make validtions happy.
def new_record?

false

end

# Dummy stub to make validtions happy.
def update_attribute
end

# Mix in that validation goodness!
include ActiveRecord::Validations

# Use validations.
validates_presence_of :number
validates_presence_of :expiration_month
validates_presence_of :expiration_year
validates_presence_of :verification_value

end

Share/Save/Bookmark

Tags: , ,

. 29 Dec 07 | Computer


Reader's Comments

  1. Hardbap |

    What about just marking the class as abstract?

    class Car < ActiveRecord::Base
    self.abstract = true
    end

  2. Ben |

    @Hardbap, I guess it’s because you can’t instantiate abstract classes.



Leave a Reply