Arstotzka
This project allows for a quick hash / json data fetching in order to avoid code that tries to crawl through a hash and has to constantly check for nil values or missing keys
also, this concern, like openstruct, allow the json to be manipulated as an object, but avoids method missing by aways having the declarated methods, even if that means nil return
Arstotzka is also usefull when you need keys case changed or data type cast as it was developed to be a bridge between a rails application and a Java API (Java APIs use cameCase for JSON keys)
Yard Documentation
https://www.rubydoc.info/gems/arstotzka/1.6.2
Instalation
- Add Arstotzka to your
Gemfile
andbundle install
:
- Install it
gem install arstotzka
- Or add Arstotka to you
Gemfile
andbundle install
gem 'arstotzka'
bundle install arstotzka
Getting Started
- Include in a class that you want to wrap a json/hash
class MyParser
include Arstotzka
end
- Declare the keys you want to crawl
class MyParser
include Arstotzka
expose :id
expose :name, :age, path: :person
attr_reader :json
def initialize(json = {})
@json = json
end
end
and let it fetch values from your hash
MyParser.new(
id: 10,
age: 22
person: {
name: 'Robert',
age: 22
}
)
this is usefull when trying to fetch data from hashes missing nodes
MyParser.new.name # returns nil
-
fully customise the way you crawl / fetch the information with Options
-
Create custom typecast
Options
- after: Name of a method to be called after on the values returned
- after_each: Name of a method to be called after each result
- cached: Indicator that, once the value has been fetched, it should be cached (false by default)
- false : no cache
- true : simple cache where nil values are not considerated cached
- :full : full cache where even nil values are cached
- case: Case of the keys from the json (lower_camel by default)
- :snake : snakecase (eg.
the_key
) - :lower_camel : lower cammel case (eg.
theKey
) - :upper_camel : upper cammel case (eg.
TheKey
)
- :snake : snakecase (eg.
- compact: Indicator telling to ignore nil values inside array (false by default)
- default: Default value (prior to casting and wrapping, see Default)
- flatten: Indicator telling that to flattern the resulting array (false by default)
- full_path: Full path to fetch the value (empty by default)
- klass: Class to be used when wrapping the final value
- json: Method that contains the hash to be parsed (
:json
by default) - path: Path where to find the sub hash that contains the key (empty by default)
- type: Type that the value must be cast into (TypeCast)
- before: method to be ran on result before any wrapping
TypeCast
The type casting, when the option type
is passed, is done through the Arstotzka::TypeCast
which can
be extended
module Arstotzka::TypeCast
def to_money_float(value)
value.gsub(/\$ */, '').to_f
end
end
class MyParser
include Arstotzka
expose :total_money, full_path: 'accounts.balance', after: :sum,
cached: true, type: :money_float
expose :total_owed, full_path: 'loans.value', after: :sum,
cached: true, type: :money_float
attr_reader :json
def initialize(json = {})
@json = json
end
private
#this method will receive the array of values resulting from the initial mapping
def sum(balances)
balances.sum if balances
end
end
object = MyParser.new(
accounts: [
{ balance: '$ 1000.50', type: 'checking' },
{ balance: '$ 150.10', type: 'savings' },
{ balance: '$ -100.24', type: 'checking' }
],
loans: [
{ value: '$ 300.50', bank: 'the_bank' },
{ value: '$ 150.10', type: 'the_other_bank' },
{ value: '$ 100.24', type: 'the_same_bank' }
]
)
object.total_money # returns 1050.36
Default
Default value returned before typecasting or class wrapping
class Star
attr_reader :name
def initialize(name:)
@name = name
end
end
class StarGazer
include Arstotzka
expose :favorite_star, full_path: 'universe.star',
default: { name: 'Sun' }, klass: ::Star
attr_reader :json
def initialize(json = {})
@json = json
end
end
star_gazer = StarGazer.new
star_gazer.favorite_star.name # returns "Sun"
star_gazer.favorite_star.class # returns Star
Configuration
Arstotzka can be configured changing the default options
class Restaurant
include Arstotzka
expose :dishes, path: 'restaurant.complete_meals'
def initialize(hash)
@hash = hash
end
end
hash = {
restaurant: {
complete_meals: {
dishes: %w[
Goulash
Spaghetti
Pizza
]
}
}
}
restaurant = Restaurant.new(hash)
restaurant.dishes # raises NoMethodError as json method is
# is not defined in Restaurant
Arstotzka.configure { json :@hash }
restaurant.dishes # returns nil as default case is lower_camel
Arstotzka.configure { |c| c.case :snake }
restaurant.dishes # return %s[Goulash Spaghetti Pizza]