Project

optionoids

0.0
The project is in a healthy, maintained state
Optionoids is a Ruby gem designed to provide a simple and flexible way to validate and check the content of option hashes. It allows developers to define checks for required keys, unexpected keys, and value conditions, making it easier to work with configuration options in Ruby applications.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Runtime

>= 7.1.0, < 9.0
 Project Readme

Optionoids

(Terrible name, I know)

Optionoids provides a simple, flexible, and concise method of validating option hashes passed to methods. Failures of validation can either raise an error or return an array of the errors. Checks can be chained together to create complex validations, and can be used to validate presence, population, types, and counts.

Installation

Install the gem and add to the application's Gemfile by executing:

$ bundle add optionoids

If bundler is not being used to manage dependencies, install the gem by executing:

$ gem install optionoids

Usage

Optionoids provides two methods on the Hash class. The expecting method is used for hard validations that will raise an error if the validation fails, while the checking method is used for soft validations that will provide an array of errors if the validation fails.

require 'optionoids'

class MyClass
  def my_method(name, options = {})
    expecting = options.expecting.with_params(name: name)
      .only_these(%i[name address age])
    expecting.that(%i[name address]).required.of_type(String)
             .and.that(:age).of_type(Integer)
  end
end

Initialization

To start a hard validation, call expecting on the hash you want to validate. This will return an instance of Optionoids::Checker.

options = { name: 'John', age: 30 }
checker = options.expecting

To start a soft validation, call checking on the hash you want to validate. This will return an instance of Optionoids::Checker.

options = { name: 'John', age: 30 }
checker = options.checking

Both methods accept a keys: argument to specify an initial key filtering state (see below). The keys argument can be a single key or an array of keys.

options = { name: 'John', age: 30, email: 'bob@foo.com' }
checker = options.expecting(keys: :name)
# or
checker = options.checking(keys: [:name, :age])

Additional Parameters

In addition to the pairs in the hash, additional pairs can be added for validation with the with_params method.

options.expecting.with_params(name: 'John', age: 30)

Filtering

The key/value pairs that a check will be performed on can be filtered to only include certain keys. Once a filter is set, all subsequent checks will only be performed on the keys that are in the filter until the filter is altered or cleared. By default, there is no filter set, and all keys in the hash will be checked. An initial filter can be set when the checker is created by passing a keys: argument to the expecting or checking methods.

that(keys) Method

Sets a set of keys that subsequent checks will be performed on.

checker = options.expecting.that(%i[name address age])
checker.keys # => [:name, :address, :age]

plus(keys) Method

Adds keys to the current filter.

checker = options.expecting.that(%i[name address]).plus(:age)
checker.keys # => [:name, :address, :age]

minus(keys) Method

Removes keys from the current filter.

checker = options.expecting.that(%i[name address age]).minus(:address)
checker.keys # => [:name, :age]

and Method

Clears the current filter.

expecting = options.expecting.that(%i[name address age])
expecting.that(:name).required.and.that(:age).populated

Alias: all

expecting = options.expecting.that(%i[name address age])
expecting.that(:name).required
expecting.all.populated

Checks

Checks are methods that can be chained together to perform validations on the keys and values in the options hash. The checks can be used to validate presence, population, types, and counts. Depending on how the checker was initialized, the checks will either raise an error or add to an array of errors (See #errors for accessing the array).

only_these(keys) Method

Checks that only the keys provided are present in the options hash. If any other keys are present, an error will be raised or added to the errors array.

expecting = options.expecting.only_these(%i[name address age])

Error raised/logged: Optionoids::Errors::UnexpectedKeys

exist Method

Checks that all the currently set filter keys are present in the current option Hash. If there are no entries in the current option Hash, an error is raised. If any of the keys are missing, an error is raised.

expecting = options.expecting.that(:name).exist

Errors raised/logged:

  • Empty hash - Optionoids::Errors::RequiredDataUnavailable
  • Missing keys - Optionoids::Errors::MissingKeys

populated Method

Checks that all the filter keys in the hash are not nil or empty. If any of the keys are nil or empty, an error is raised or added to the errors array. It does not error if the keys do not exist in the hash.

expecting = options.expecting.that(:name).populated

Error raised/logged: Optionoids::Errors::UnexpectedBlankValue

Alias: all_populated

blank Method

Checks that all the filter keys in the hash are nil or empty. If any of the keys are not nil or empty, an error is raised or added to the errors array. It does not error if the keys do not exist in the hash.

expecting = options.expecting.that(:name).blank

Error raised/logged: Optionoids::Errors::UnexpectedPopulatedValue

Alias: all_blank

not_nil_values Method

Checks that all the filter keys in the hash are not nil. If any of the keys are nil, an error is raised or added to the errors array. It does not error if the keys do not exist in the hash.

expecting = options.expecting.that(:name).not_nil_values

Error raised/logged: Optionoids::Errors::UnexpectedNilValue

nil_values Method

Checks that all the filter keys in the hash are nil. If any of the keys are not nil, an error is raised or added to the errors array. It does not error if the keys do not exist in the hash.

expecting = options.expecting.that(:name).nil_values

Error raised/logged: Optionoids::Errors::UnexpectedNotNilValue

one_or_none Method

Checks that at most one of the filter keys in the hash are present. If more than one of the keys are present, an error is raised or added to the errors array. It does not consider values, only the presence of the keys.

expecting = options.expecting.that(%i[name age]).one_or_none

Error raised/logged: Optionoids::Errors::UnexpectedMultipleKeys

just_one Method

Checks that exactly one of the filter keys in the hash are present. If none or more than one of the keys are present, an error is raised or added to the errors array. It does not consider values, only the presence of the keys.

expecting = options.expecting.that(%i[name age]).just_one

Errors raised/logged:

  • Empty hash - Optionoids::Errors::RequiredDataUnavailable
  • None or more than one keys - Optionoids::Errors::UnexpectedMultipleKeys

one_or_more Method

Checks that at least one of the filter keys in the hash are present. If none of the keys are present, an error is raised or added to the errors array. It does not consider values, only the presence of the keys.

expecting = options.expecting.that(%i[name age]).one_or_more

Error raised/logged: Optionoids::Errors::ExpectedMultipleKeys

of_types(types) Method

Checks that the values of the filter keys in the hash are of the types provided. If any of the values are not of the expected type, an error is raised or added to the errors array. It does not error if the keys do not exist in the hash or if the value is nil.

expecting = options.expecting.that(:name).of_types(String, Symbol)

Error raised/logged: Optionoids::Errors::UnexpectedValueType

Alias: of_type, types, type

possible_values(variants) Method

Checks that the values of the filter keys in the hash are one of the possible values provided. If any of the values are not one of the possible values, an error is raised or added to the errors array. It does not error if the keys do not exist in the hash or if the value is nil.

expecting = options.expecting.that(:name).possible_values('John', 'Jane', 'Doe')

Error raised/logged: Optionoids::Errors::UnexpectedValueVariant

Convenience Methods

The Optionoids::Checker class provides several convenience methods to make it easier to perform common checks. These methods are available on both hard and soft checkers.

identifier Method

Checks that the value of the filter key is a valid identifier. A valid identifier is a populated String or Symbol.

expecting = options.expecting.that(:name).identifier

Errors raised/logged:

  • If the wrong type: Optionoids::Errors::UnexpectedValueType
  • If the value is nil or empty: Optionoids::Errors::UnexpectedBlankValue

flag Method

Checks that the value of the filter key is a populated boolean. A boolean is either true or false.

expecting = options.expecting.that(:active).flag

Errors raised/logged:

  • If the wrong type: Optionoids::Errors::UnexpectedValueType
  • If the value is nil or empty: Optionoids::Errors::UnexpectedBlankValue

required Method

Checks that the filter key is present and populated in the options hash.

expecting = options.expecting.that(:name).required

Errors raised/logged:

  • If the hash is empty: Optionoids::Errors::RequiredDataUnavailable
  • Not present: Optionoids::Errors::MissingKeys
  • If the value is nil or empty: Optionoids::Errors::UnexpectedBlankValue

Soft Errors

If the checker was initialized with checking, the errors will be collected in an array. You can access the errors using the errors method. A predicate method failed? is also available to check if there are any errors.

checker = options.checking.that(:name).required
checker.errors # => ["Missing keys: name", "Unexpected blank value for key: name"]
checker.failed? # => true

Data Access / Debugging

current_options Method

Returns the current filtered options Hash that is being checked.

checker = options.expecting.that(:name).current_options
# => { name: 'John' }

global_options Method

Returns the original options Hash that was passed to the checker. Options added with with_params are included in this hash.

checker = options.expecting.with_params(name: 'John').global_options
# => { name: 'John', age: 30 }

keys Method

Returns the keys that are currently being checked. This is useful to see which keys are in the current filter.

checker = options.expecting.that(:name, :age).keys
# => [:name, :age]

Future Enhancements

  • Add support for regex checks on values.
  • Add common checks using regex (e.g., email, URL).
  • Add support for range checks on numeric & date values.
  • Implement a similar API for cleaning the options hash.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/optionoids. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Optionoids project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.