By Mislav on 31 Aug 2008 in rails
Sometimes you don’t need database persistence for your models. Ryan Bates describes this as the non-ActiveRecord model in his screencasts.
What if you need validations? I’ve tried it, thinking that I only need to mix-in ActiveRecord::Validations module:
class Person
attr_accessor :name, :age
include ActiveRecord::Validations
validates_presence_of :name
end
It turned out this doesn’t work. The Validations module expects our class to look like an ActiveRecord::Base subclass—at least to some extent. But, with a few methods more, we can easily make this happen.
At include time, the Validations module of Rails 2.1 expects these methods to be defined:
save, save!, update_attribute and new_record?.
Here is the code for a minimal model that uses validations:
class Person
attr_accessor :name, :age
def initialize(attrs = {})
for key, value in attrs
update_attribute(key, value)
end
@new_record = true
end
def save
# your saving logic goes here
# ...
@new_record = false
return true # if saving was a success
end
alias :save! :save
def update_attribute(key, value)
send "#{key}=", value
end
def new_record?() @new_record; end
# the fun part:
include ActiveRecord::Validations
validates_presence_of :name
end
This class definition doesn’t raise errors. Let’s try it out:
>> me = Person.new :age => 24
=> #<Person:0x212f5a0 @new_record=true, @age=23>
>> me.save
=> false
Success! Validations refused to save the instance because the name attribute is missing:
>> me.name = "Mislav"
=> "Mislav"
>> me.save
=> true
>> me.new_record?
=> false
Of course, we can inspect the validation error messages in a way identical to doing it in ActiveRecord. Your custom view helpers for displaying validation errors should continue working without modifications.