https://github.com/nowlinuxing/sumaki
Sumaki is a wrapper for structured data like JSON.
https://github.com/nowlinuxing/sumaki
ruby rubygems wrapper-library
Last synced: about 2 months ago
JSON representation
Sumaki is a wrapper for structured data like JSON.
- Host: GitHub
- URL: https://github.com/nowlinuxing/sumaki
- Owner: nowlinuxing
- License: mit
- Created: 2023-02-19T16:08:13.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-06-06T03:54:50.000Z (about 2 years ago)
- Last Synced: 2025-07-28T17:49:20.260Z (11 months ago)
- Topics: ruby, rubygems, wrapper-library
- Language: Ruby
- Homepage:
- Size: 93.8 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Sumaki
---
[](https://badge.fury.io/rb/sumaki)

[](https://codeclimate.com/github/nowlinuxing/sumaki/maintainability)
[](https://codeclimate.com/github/nowlinuxing/sumaki/test_coverage)
**Sumaki** is a wrapper for structured data like JSON.
Since Sumaki wraps the target data as it is, rather than parsing it using a schema, the original data can be referenced at any time.
This makes it easy to add or modify definitions as needed while checking the target data.
This feature may be useful when there is no document defining the structure of the data, or when the specification is complex and difficult to grasp, and the definition is written little by little starting from the obvious places.
```ruby
class AnimeList
include Sumaki::Model
repeated :anime
field :name
class Anime
include Sumaki::Model
singular :studio
field :title
class Studio
include Sumaki::Model
field :name
end
end
end
data = {
name: 'Winter 2023',
anime: [
{
title: 'The Vampire Dies in No Time',
studio: {
name: 'MADHOUSE Inc.'
}
},
{
title: '“Ippon” again!',
studio: {
name: 'BAKKEN RECORD'
}
}
]
}
anime_list = AnimeList.new(data)
anime_list.name #=> 'Winter 2023'
anime_list.anime[0].title #=> 'The Vampire Dies in No Time'
anime_list.anime[0].studio.name #=> 'MADHOUSE Inc.'
anime_list.anime[0].object #=> { title: 'The Vampire Dies in No Time', studio: { name: 'MADHOUSE Inc.' } }
```
## Installation
Install the gem and add to the application's Gemfile by executing:
$ bundle add sumaki
If bundler is not being used to manage dependencies, install the gem by executing:
$ gem install sumaki
## Usage
Include `Sumaki::Model` module in the class that wraps the data, and give the data when creating the instance.
```ruby
class Anime
include Sumaki::Model
end
Anime.new({})
```
Only this does not give access to fields or structured data, so the following declarations need to be added.
### Access to the fields
By declaring `field`, you can access the field.
```ruby
class Anime
include Sumaki::Model
field :title
field :url
end
```
```ruby
# Read the field values
anime = Anime.new({ title: 'The Vampire Dies in No Time', url: 'https://sugushinu-anime.jp/' })
anime.title #=> 'The Vampire Dies in No Time'
anime.url #=> 'https://sugushinu-anime.jp/'
```
```ruby
# Write the field value
anime = Anime.new({})
anime.title = 'The Vampire Dies in No Time'
anime.title #=> 'The Vampire Dies in No Time'
```
If the data contains attributes not declared in the field, it raises no error and is simply ignored.
#### Type casting
When a type is specified, it will be typecast.
```ruby
class Character
include Sumaki::Model
field :age, :int
end
character = Character.new({ age: '208' })
character.age #=> 208
```
Types are:
* `:int`
* `:float`
* `:string`
* `:bool`
* `:date`
* `:datetime`
### Access to the sub object
By declaring `singular`, you can access the sub object.
```ruby
class Book
include Sumaki::Model
singular :company
field :title
class Company
include Sumaki::Model
field :name
end
end
```
```ruby
data = {
title: 'The Ronaldo Chronicles',
company: {
name: 'Autumn Books',
}
}
# Read from the sub object
book = Book.new(data)
book.company.name #=> 'Autumn Books'
```
```ruby
# Build a sub object
book = Book.new({})
book.build_company(name: 'Autumn Books')
book.company #=> #
```
Sub object is wrapped with the class inferred from the field name under the original class.
This can be changed by specifying the class to wrap.
```ruby
class Book
include Sumaki::Model
singular :author, class_name: 'Character'
field :title
class Character
include Sumaki::Model
field :name
end
end
data = {
title: 'The Ronaldo Chronicles',
author: {
name: 'Ronaldo'
}
}
book = Book.new(data)
book.author.class #=> Book::Character
```
### Access to the repeated sub objects
By declaring `repeated`, you can access the repeated sub objects as an Array.
```ruby
class Company
include Sumaki::Model
repeated :member
field :name
class Member
include Sumaki::Model
field :name
end
end
```
```ruby
data = {
name: 'The Ronaldo Vampire Hunter Agency',
member: [
{ name: 'Ronaldo' },
{ name: 'Draluc' },
{ name: 'John' }
]
}
# Read from the sub object
company = Company.new(data)
company.member.size #=> 3
company.member[2].name #=> 'John'
```
```ruby
# Build a sub object
company = Company.new({})
company.member.build(name: 'John')
company.member[0].name #=> 'John'
```
The `class_name` option can also be used to specify the class to wrap.
### Access to the parent object
Parent object can be referenced from sub object by `#parent` method.
```ruby
class Character
include Sumaki::Model
singular :child
field :name
class Child
include Sumaki::Model
field :name
end
end
data = {
name: 'Draus',
child: {
name: 'Draluc'
}
}
character = Character.new(data)
character.child.name #=> 'Draluc'
character.child.parent.name #=> 'Draus'
```
### Enumerations
By declaring `enum`, You can map a field to the specified value.
```ruby
class Character
include Sumaki::Model
field :name
enum :type, { vampire: 1, vampire_hunter: 2, familier: 3, editor: 4 }
end
```
```ruby
data = {
name: 'John',
type: 3
}
# Read the enum
character = Character.new(data)
character.type.name #=> :familier
character.type.familier? #=> true
```
```ruby
# Write the enum value
character = Character.new({})
character.type = 1
character.type.name #=> :vampire
character.type = :vampire_hunter
character.type.name #=> :vampire_hunter
character.type.familier!
character.type.name #=> :familier
```
## Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/nowlinuxing/sumaki.
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).