validates_method_of

written by seb on August 28th, 2006 @ 10:02 AM

I personally was looking for a way to validate a specific object method in a model.

In my case I would for exemple to allow only an admin or owner to post an article.

For this I made an extention to the active record ’s validations class methods to allow me to do this simply and with flexibility.

validates_method_of.rb: (updated after Jean-François comments)
module ActiveRecord
  module Validations
    module ClassMethods
      # Validates whether the value of the specified object method is correct from matching
      # one of the accepted values provided or if different than the excepted one
      # 
      #   class Article < ActiveRecord::Base
      #     validates_method_of :user, :method => 'role', :only => %w( owner admin )
      #   end
      # 
      # Configuration options:
      # * <tt>method</tt> - The method that will be validate
      # * <tt>message</tt> - A custom error message (default is: "not authorized")
      # * <tt>only</tt> - An enumerable object of items that the value should be part of
      # * <tt>except</tt> - An enumerable object of items that the value shouldn't be part of
      def validates_method_of(*attr_names)
        configuration = { :message => 'not authorized', :on => :save }
        configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)

        if configuration[:only]
          enum = configuration[:only]
          validates_each(attr_names, configuration) do |record, attr_name, value|
            if !value.blank?
              method = value.send(configuration[:method].to_s)
              record.errors.add(attr_name, configuration[:message]) if !enum.include?(method)
            end
          end
        else
          enum = configuration[:except]
          validates_each(attr_names, configuration) do |record, attr_name, value|
            if !value.blank?
              method = value.send(configuration[:method].to_s)
              record.errors.add(attr_name, configuration[:message]) if enum.include?(method)
            end
          end
        end
      end
    end
  end
end

I personally put this file in my lib directory and loaded it from config/environment.rb like this:

require 'validates_method_of'

Comments are closed