Validation Assertions
I like to test my validations. While I don’t really care to test the underlying code that runs the validations (I trust the Rails team to make sure they work as advertised) I do like the reassurance that I didn’t screw up. So, I’ve written this small plugin to help me test my validations.
It works simply. In one of your models you’ve got a validation like this:class User < ActiveRecord::Base
validates_presence_of :name
validates_length_of :name, :in => 4..26
validates_uniqueness_of :name
endclass UserTest < Test::Unit::TestCase
# Assert that a User's name must exist for validations to pass.
def test_validates_presence_of_name
assert_validates_presence_of User, :name
end
# Assert that a User's name must be at least 4 characters in length for
# validations to pass.
def test_validates_minimium_length_of_name
assert_validates_minimum_length_of User, :name, 4
end
# Assert that a User's name must be less than 26 characters in length for
# validations to pass.
def test_validates_maximum_length_of_name
assert_validates_maximum_length_of User, :name, 26
end
# Assert that a User's name must be unique for validations to pass.
def test_validates_uniqueness_of_name
assert_validates_uniqueness_of User, :name
end
endThat’s it. Now you can rest easy know that your validations are really, really, really in place.
To install the plugin:script/plugin install http://validation-assertions.googlecode.com/svn/trunk/validation_assertions/
Associations are the Best
Person and Article models. The Article model has a foreign key: person_id. In this application the best way to get the latest Article for a Person is:
class Person < ActiveRecord::Base
has_one :latest_article,
:class_name => 'Article',
:order => 'articles.published_at DESC'
endPerson’s Articles. Something like:
has_many :articles,
:order => 'articles.published_at DESC'person.articles.firstPerson’s Articles form the database just to snag the most recent one.
You could also do something like this:
class Person < ActiveRecord::Base
def latest_article
articles.find :first,
:conditions => 'articles.published_at DESC'
end
endThat’d be a lot better than grabbing all the Articles but it still wouldn’t be great. Multiple calls to person.latest_article would execute multiple calls to the database. Slow.
Using associations is sexier than a simple finder method because you get caching for free. After the first person.latest_article call subsequent calls hit the cache. Very nice.
Now, for the impetus of this post. I was implementing just what I’ve outlined here, only slightly more complex. Instead of Articles simply belonging to People, in my application Articles belong to People through Mentions.
In this scenario, the latest_article association shown above doesn’t work because you cannot (yet) have has_one_through associations. You can do has_many_through to your hearts content, just no has_one_through.
I’m not the first to want this feature.
Much like my ticket regarding the lame behavior of validates_presence_of, it looks like this won’t be resolved soon.
Oh well, I guess I’ll have to write a dreaded finder method.