OptionsHash
An OptionsHash is a definition of required and optional keys in an options hash
Installation
Add this line to your application's Gemfile:
gem 'options_hash'
And then execute:
$ bundle
Or install it yourself as:
$ gem install options_hash
Usage
A simple use case goes something like this:
require 'net/http'
def http_get options
options = OptionsHash.parse(options) do
required :host, :path
optional :port, default: 80
end
Net::HTTP.get(options.host, options.path, options.port)
end
http_get
# => ArgumentError: wrong number of arguments (0 for 1)
http_get({})
# => ArgumentError: required options: :host, :path
http_get(host: 'google.com')
# => ArgumentError: required options: :path
http_get(host: 'google.com', path: '/')
# => "<HTML><HEAD><meta ht..."
http_get(host: 'google.com', path: '/', port: 81)
# => Net::HTTPRequestTimeOut
A possibly more common use case:
class Person
class Options < OptionsHash
required :name
optional :age, default: 31
end
def initialize options
@options = Options.parse(options)
end
attr_reader :options
end
me = Person.new({}) # => ArgumentError: required options: :name
me = Person.new(name: 'Jared Grippe')
me.options.name # => "Jared Grippe"
me.options.age # => 31
me.options.to_hash # => {:name=>"Jared Grippe", :age=>31}
me = Person.new(name: 'Jared Grippe', age: 25)
me.options.name # => "Jared Grippe"
me.options.age # => 25
Advanced usage:
class PersonOptions < OptionsHash
required :name
optional :favorite_color
optional :species, default: :human
end
PersonOptions.options # => {
# :name=>required without default,
# :favorite_color=>optional without default,
# :species=>optional with default}
PersonOptions[:name] # => required without default
PersonOptions[:name].required? # => true
PersonOptions[:name].has_default? # => false
PersonOptions[:name].has_default_proc? # => false
PersonOptions[:name].default # => nil
PersonOptions.parse({}) # ArgumentError: required options: :name
PersonOptions.parse(name: 'Steve')
# => #<PersonOptions {:name=>"Steve", :favorite_color=>nil, :species=>:human}>
PersonOptions.parse(name: 'Steve', favorite_color: 'blue')
# => #<PersonOptions {:name=>"Steve", :favorite_color=>"blue", :species=>:human}>
PersonOptions.parse(name: 'Steve', species: :robot)
# => #<PersonOptions {:name=>"Steve", :favorite_color=>"blue", :species=>:robot}>
options = PersonOptions.parse(name: 'Steve', species: :robot)
options.name # => "Steve"
options.favorite_color # => nil
options.species # => :robot
options.given? :name # => true
options.given? :favorite_color # => false
options.given? :species # => true
options.to_hash # => {:name=>"Steve", :favorite_color=>nil, :species=>:robot}
All options can take a block to determine their default value:
class PersonOptions < OptionsHash
required(:first_name, :last_name) { |name| name.to_sym }
optional :full_name, default: ->{ "#{first_name} #{last_name}" }
end
PersonOptions
# => PersonOptions(required: [:first_name, :last_name], optional: [:full_name])
options = PersonOptions.parse(first_name: 'Jared', last_name: 'Grippe')
# => #<PersonOptions {:first_name=>:Jared, :last_name=>:Grippe, :full_name=>"Jared Grippe"}>
options.given_options
# => {:first_name=>"Jared", :last_name=>"Grippe"}
options[:first_name] # => :Jared
options[:last_name] # => :Grippe
options[:full_name] # => "Jared Grippe"
Option hashes can inherit from other option hashes
class AnimalOptions < OptionsHash
required :species
optional :alive, default: true
end
class DogOptions < AnimalOptions
required :name, :breed
end
AnimalOptions
# => AnimalOptions(required: [:species], optional: [:alive])
DogOptions
# => DogOptions(required: [:breed, :name, :species], optional: [:alive])
DogOptions[:alive].default # => true
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request