Hey, my first rails plugin

Ruby on Rails allows for plugins to extend its functionality. My first attempt at one is nothing special but I am going to blog about it anyway 😀

I needed a way to check if a number is within a range before saving a record to the database. Rails has a number of good validations built in, but not one that does that. In two or three hours, I was able to piece together a simple plugin that adds “validates_range_of” to my AR models. The code is a little ugly until I can get Greg to install a syntax highlighting plugin for this blog.

module ActiveRecord
module Validations
module ClassMethods
def validates_range_of(*attrs)
options = {  :on => :save  }
options.update(attrs.pop) if attrs.last.is_a?(Hash)
unless options[:message]
if options[:maximum] && options[:minimum]
options[:message] = 'must be betweeen ' + options[:minimum].to_s + ' and ' + options[:maximum].to_s
elsif options[:maximum]
options[:message] = 'must be less than or equal to ' + options[:maximum].to_s
elsif options[:minimum]
options[:message] = 'must be greater than or equal to ' + options[:minimum].to_s
raise ArgumentError, 'Range unspecified.  Specify the :maximum and/or :minimum.'
validates_numericality_of( attrs, options )
validates_each(attrs, options) do |record, attr_name, value|
if ((!options[:maximum].nil?) && (!options[:minimum].nil?)) &&
(value > options[:maximum] || value < options[:minimum])
record.errors.add( attr_name, options[:message] )
elsif (!options[:maximum].nil?) && value > options[:maximum]
record.errors.add( attr_name, options[:message] )
elsif (!options[:minimum].nil?) && value < options[:minimum]
record.errors.add( attr_name, options[:message] )

As you can see this plugin extends AR::Validations. So my models can use validates_range_of to check minimum and maximum values. Let’s look at the BJCP Scoresheet I needed it for:

class BjcpScoresheet < ActiveRecord::Base
belongs_to :brew_session
validates_associated :brew_session
validates_range_of :brew_session_id, { :minimum => 1, :message => 'does not belong to a brew session' }
validates_range_of :aroma_score, { :minimum => 1, :maximum => 12, :only_integer => true }
validates_range_of :appearance_score, { :minimum => 1, :maximum => 3, :only_integer => true }
validates_range_of :flavor_score, { :minimum => 1, :maximum => 20, :only_integer => true }
validates_range_of :mouthfeel_score, { :minimum => 1, :maximum => 10, :only_integer => true }
validates_range_of :impression_score, { :minimum => 1, :maximum => 10, :only_integer => true }

How nice – reusable user input validation.


2 thoughts on “Hey, my first rails plugin”

  1. oooo a brewer and ruby programmer… You should make something to compete with ProMash and Beermith! Open Source FTW!

  2. Hi Tony,

    😀 BrewSession will compete with Promash and Beersmith, except we’re keeping it to ourselves. It will be free to use however. There is an open-source brewing software movement starting at http://www.beerhackers.com/ and we’re going to work with them to inter-operate.

Leave a Reply