Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/evilmartians/evil-struct
Nested structure with type constraints, based on the `dry-initializer` DSL
https://github.com/evilmartians/evil-struct
constraints dsl ruby
Last synced: 3 months ago
JSON representation
Nested structure with type constraints, based on the `dry-initializer` DSL
- Host: GitHub
- URL: https://github.com/evilmartians/evil-struct
- Owner: evilmartians
- License: mit
- Created: 2016-11-20T17:25:38.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2017-01-28T21:14:28.000Z (almost 8 years ago)
- Last Synced: 2024-07-22T08:23:31.022Z (4 months ago)
- Topics: constraints, dsl, ruby
- Language: Ruby
- Size: 18.6 KB
- Stars: 10
- Watchers: 40
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Evil::Struct
Nested structure with type constraints, based on the [dry-initializer][dry-initializer] DSL.
[![Gem Version][gem-badger]][gem]
[![Build Status][travis-badger]][travis]
[![Dependency Status][gemnasium-badger]][gemnasium]
[![Inline docs][inch-badger]][inch]## Installation
Add this line to your application's Gemfile:
```ruby
gem 'evil-struct'
```And then execute:
$ bundle
Or install it yourself as:
$ gem install evil-struct
## Synopsis
The structure is like [dry-struct][dry-struct] except for it controls optional attributes and default values aside of type constraints.
Its DSL is taken from [dry-initializer][dry-initializer]. Its method `attribute` is just an alias for `option`.
```ruby
require "evil-struct"
require "dry-types"class Product < Evil::Struct
attribute :title
attribute :price, Dry::Types["coercible.float"]
attribute :quantity, Dry::Types["coercible.int"], default: proc { 0 }# shared options
attributes optional: true do
attribute :subtitle
attribute :description
end
end# Accepts both symbolic and string keys.
# Class methods `[]`, `call`, and `load` are just aliases for `new`
product = Product[title: "apple", "price" => "10.9", description: "a fruit"]# Attributes are available via methods or `[]`
product.title # => "apple"
product[:price] # => 10.9
product["quantity"] # => 0
product.description # => "a fruit"# unassigned value differs from `nil`
product.subtitle # => Dry::Initializer::UNDEFINED# Raises in case a mandatory value not assigned
Product.new # BOOM! because neither title, nor price are assigned# Hashifies all attributes except for undefined subtitle
# You can use `dump` as an alias for `to_h`
product.to_h
# => { title: "apple", price: 10.9, description: "a fruit", quantity: 0 }# The structure is comparable to any object that responds to `#to_h`
product == { title: "apple", price: 10.9, description: "a fruit", quantity: 0 }
# => true
```The structure is designed for immutability. That's why it doesn't contain writers (but you can define them by yourself via `attr_writer`).
Instead of mutating current instance, you can merge another hash to the object via `merge` or `deep_merge`.
```ruby
new_product = product.merge(title: "orange")
new_product.class # => Product
new_product.to_h
# => { title: "orange", price: 10.9, description: "a fruit", quantity: 0 }# you can merge any object that responds to `to_h` or `to_hash`
other = Product[title: "orange", price: 12]
new_product = product.merge(other)
new_product.to_h
# => { title: "orange", price: 12, description: "a fruit", quantity: 0 }# merge_deeply (deep_merge) gracefully merge nested hashes or hashified objects
grape = Product.new title: "grape",
price: 30,
description: { country: "FR", year: 2016, sort: "Merlot" }new_grape = grape.merge_deeply description: { year: 2017 }
new_grape.to_h
# => {
# title: "grape",
# price: 30,
# description: { country: "FR", year: 2017, sort: "Merlot" }
# }
```## Compatibility
Tested under rubies [compatible to MRI 2.2+](.travis.yml).
## Contributing
* [Fork the project](https://github.com/dry-rb/dry-initializer)
* Create your feature branch (`git checkout -b my-new-feature`)
* Add tests for it
* Commit your changes (`git commit -am '[UPDATE] Add some feature'`)
* Push to the branch (`git push origin my-new-feature`)
* Create a new Pull Request## License
The gem is available as open source under the terms of the [MIT License](./LICENSE.txt).
[dry-initializer]: https://rom-rb.org/gems/dry-initializer
[dry-struct]: https://rom-rb.org/gems/dry-struct
[gem-badger]: https://img.shields.io/gem/v/evil-struct.svg?style=flat
[gem]: https://rubygems.org/gems/evil-struct
[gemnasium-badger]: https://img.shields.io/gemnasium/evilmartians/evil-struct.svg?style=flat
[gemnasium]: https://gemnasium.com/evilmartians/evil-struct
[inch-badger]: http://inch-ci.org/github/evilmartians/evil-struct.svg
[inch]: https://inch-ci.org/github/evilmartians/evil-struct
[travis-badger]: https://img.shields.io/travis/evilmartians/evil-struct/master.svg?style=flat
[travis]: https://travis-ci.org/evilmartians/evil-struct