<commit_before># Hashr

Hashr is a very simple and tiny class derived from Ruby's core Hash class which makes using nested hashes for configuration (and other purposes) easier and less repetive and error prone.

It supports the following features:

* method read and write access
* automatic predicate (boolean, i.e. ?) methods
* easy defaults
* easy inclusion of modules into nested hashes
* automatic symbolized keys

## Usage

Directly use Hashr instances like this:

    config = Hashr.new('foo' => { 'bar' => 'bar' })

    config.foo?     # => true
    config.foo      # => { :bar => 'bar' }

    config.foo.bar? # => true
    config.foo.bar  # => 'bar'

    config.foo.bar = 'BAR'
    config.foo.bar # => 'BAR'

    config.foo.baz = 'baz'
    config.foo.baz # => 'baz'

Be aware that by default missing keys won't raise a method missing error but instead behave like Hash access:

    config = Hashr.new
    config.foo? # => false
    config.foo  # => nil

You can make Hashr to raise an IndexError though like this:

    Hashr.raise_missing_keys = true
    config = Hashr.new
    config.foo? # => false
    config.foo  # => raises an IndexError "Key :foo is not defined."

Derive a custom class to define defaults like this:

    class Config < Hashr
      define :foo => { :bar => 'bar' }
    end

    config = Config.new
    config.foo.bar # => 'bar'

Include modules to nested hashes like this:

    class Config < Hashr
      module Boxes
        def count<commit_msg>tweak readme<commit_after># Hashr

Hashr is a very simple and tiny class derived from Ruby's core Hash class which makes using nested hashes for configuration (and other purposes) easier and less repetive and error prone.

It supports the following features:

* method read and write access
* automatic predicate (boolean, i.e. `?`) methods
* easy defaults
* easy inclusion of modules into nested hashes
* automatic symbolized keys

## Usage

Directly use Hashr instances like this:

    config = Hashr.new('foo' => { 'bar' => 'bar' })

    config.foo?     # => true
    config.foo      # => { :bar => 'bar' }

    config.foo.bar? # => true
    config.foo.bar  # => 'bar'

    config.foo.bar = 'bar!'
    config.foo.bar # => 'bar!'

    config.foo.baz = 'baz'
    config.foo.baz # => 'baz'

Be aware that by default missing keys won't raise a method missing error but instead behave like Hash access:

    config = Hashr.new
    config.foo? # => false
    config.foo  # => nil

You can make Hashr to raise an `IndexError` though like this:

    Hashr.raise_missing_keys = true
    config = Hashr.new
    config.foo? # => false
    config.foo  # => raises an IndexError "Key :foo is not defined."

Derive a custom class to define defaults like this:

    class Config < Hashr
      define :foo => { :bar => 'bar' }
    end

    config = Config.new
    config.foo.bar # => 'bar'

Include modules to nested hashes like this:

    class Config < Hashr
      module Boxes
        def count
{'fraction_non_alphanumeric': 0.10057374282821464, 'fraction_numerical': 0.0, 'mean_word_length': 2.8294573643410854, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2666558', 'n_tokens_mistral': 907, 'n_tokens_neox': 868, 'n_words': 348}