Peter Marklund

Peter Marklund's Home

2008-06-16

Rails Tip: Validating Option Arguments

I think it's a good convention to validate options arguments passed to methods, i.e. to make sure they have valid keys and values. Misspellings can otherwise lead to unnecessary debugging sessions. Rails comes with the 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 and RSpec specification:

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

# Rspec:

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

1 comment(s)

Comments

Erik said 2009-01-23 11:06:

I replicated your method, put it in a file in lib but I get: undefined method `assert_value' for #<Hash:0x31ab154> when I try to call it from within a model class. Any ideas? TIA
--------------------------------------------------------------------------------