<commit_before># Contextuable

Better Structs for many applications.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'contextuable'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install contextuable

## Usage

__Extended OpenStruct:__

```ruby
  context = Contextuable.new(name: 'John', surname: 'Doe')
  context.name # => 'John'
  context.name_provided? # => true
  context.surname # => 'Doe'
  context.foo_provided? # => false
  context.foo = :bar
  context.foo_provided? # => true
  context.foo # => :bar
  context.to_h # => {:name=>"John", :surname=>"Doe", :foo=>:bar}
```

_more complex example_
```ruby
class Input < Contextuable
  permit  :name, :city, :address, :phone_number, :free_text, :country_code,
    :country, :zip, :types
  defaults types: ['lodging']
  aliases :name, :hotel_name
  aliases :phone_number, :telephone

  def long_name
    [name, address, city].join(', ')
  end

  def types
    Array.wrap(args[:types])
  end
end

i = Input.new(name: 'Hotel', city: 'Barcelona', address: 'Happy street', not_permitted: 'dangerous')
i.types
# => ["lodging"]
i.long_name
# => "Hotel, Happy street, Barcelona"
i.hotel_name
# => "Hotel"
i.phone_number_provided?
# => false
i.not_permitted
# => nil
```

### Building better Structs

**required**
```ruby
class Example < Contextuable
  required :required_arg
end

Example.new(foo: :bar)
#=> Error Contextuable::RequiredFieldNotPresent
```

**aliases**
```ruby
class Example < Contextuable
  aliases :hello, :greeting, :welcome
end
ex = Example.new(hello: 'Hey!')
# => #<Example:0x007fd88ba30398 @args={:hello=>"Hey!"}>
ex.hello
# => "Hey!"
ex.greeting
# => "Hey!"
ex.welcome
# => "Hey!"
```

**defaults**
```ruby
class Example2 < Contextuable
  defaults foo: :bar, bar: :foo
end
ex = Example2.new
ex.foo
 => :bar
ex.bar
 => :foo
ex2 = Example2.new(foo: 'something', bar: true)
ex2.foo
 => 'something'
ex2.bar
 => true
```

**ensure_presence**<commit_msg>improve readme<commit_after># Contextuable

Better Structs for many applications.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'contextuable'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install contextuable

## Usage

__Extended OpenStruct:__

```ruby
  context = Contextuable.new(name: 'John', surname: 'Doe')
  context.name # => 'John'
  context.name_provided? # => true
  context.surname # => 'Doe'
  context.foo_provided? # => false
  context.foo_not_provided? # => true
  context.foo = :bar
  context.foo_provided? # => true
  context.foo_not_provided? # => false
  context.foo # => :bar
  context.to_h # => {:name=>"John", :surname=>"Doe", :foo=>:bar}
```

_more complex example_
```ruby
class Input < Contextuable
  permit  :name, :city, :address, :phone_number, :free_text, :country_code,
    :country, :zip, :types
  defaults types: ['lodging']
  aliases :name, :hotel_name
  aliases :phone_number, :telephone

  def long_name
    [name, address, city].join(', ')
  end

  def types
    Array.wrap(args[:types])
  end
end

i = Input.new(name: 'Hotel', city: 'Barcelona', address: 'Happy street', not_permitted: 'dangerous')
i.types
# => ["lodging"]
i.long_name
# => "Hotel, Happy street, Barcelona"
i.name
# => "Hotel"
i.hotel_name
# => "Hotel"
i.phone_number_provided?
# => false
i.not_permitted
# => nil
```

### Building better Structs

**required**
```ruby
class Example < Contextuable
  required :required_arg
end

Example.new(foo: :bar)
#=> Error Contextuable::RequiredFieldNotPresent
```

**aliases**
```ruby
class Example < Contextuable
  aliases :hello, :greeting, :welcome
end
ex = Example.new(hello: 'Hey!')
# => #<Example:0x007fd88ba30398 @args={:hello=>"Hey!"}>
ex.hello
# => "Hey!"
ex.greeting
# => "Hey!"
ex.welcome
# => "Hey!"
```

**defaults**
```ruby
class Example2 < Contextuable
  defaults foo: :bar, bar: :foo
end
ex = Example2.new
ex.foo
# => :bar
ex.bar
# => :foo
ex.foo = :hello
ex.foo
# => :hello

ex2 = Example2.new(foo: 'something', bar: true)
ex2.foo
# => 'something'
ex2.bar
# => true
```

**ensure_presence**
{'fraction_non_alphanumeric': 0.17001469867711905, 'fraction_numerical': 0.008329250367466928, 'mean_word_length': 4.540027137042062, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 59, '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': '5719032', 'n_tokens_mistral': 1555, 'n_tokens_neox': 1468, 'n_words': 370}