Peter Marklund

Peter Marklund's Home

Mon May 12 2008 06:24:47 GMT+0000 (Coordinated Universal Time)

Rails Tip: Validating Option Arguments in your Methods

I think it's a good convention to validate that options passed to methods have valid keys and values. Misspellings can otherwise lead to unnecessary debugging sessions. Rails comes with the Hash#assert_valid_keys method. I added the assert_value method:

module ActiveSupport #:nodoc:
  module CoreExtensions #:nodoc:
    module Hash #:nodoc:
      module Keys
        # Assert that option with given key is in list
        def assert_value(key, options = {})
          options.assert_valid_keys([:in])
          if !(options[:in].map(&:to_s) + ['']).include?(self[key].to_s)
            raise(ArgumentError, "Invalid value '#{self[key]}' for option '#{key}' must be one of '#{options[:in].join(', ')}'")
          end          
        end
      end
    end
  end
end

Example usage:

  def price(feature_set_ids, options = {})
    options.assert_valid_keys([:billing_period])
    options.assert_value(:billing_period, :in => ["annual", "monthly"])
    ...

Corresponding RSpec specifications:

    it "cannot be invoked with an invalid option" do
      lambda {
        @campaign.price([23], :foobar => true)        
      }.should raise_error(ArgumentError)
    end
    
    it "cannot be invoked with an invalid billing period" do
      lambda {
        @campaign.price([23], :billing_period => :foobar)        
      }.should raise_error(ArgumentError)      
    end