hash19 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -0
- data/.ruby-gemset +0 -0
- data/.ruby-version +0 -0
- data/.travis.yml +1 -1
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +19 -7
- data/Rakefile +0 -0
- data/hash19.gemspec +1 -0
- data/lib/hash19/core.rb +2 -2
- data/lib/hash19/core_helpers.rb +0 -0
- data/lib/hash19/lazy_value.rb +0 -0
- data/lib/hash19/resolvers.rb +3 -3
- data/lib/hash19/version.rb +1 -1
- data/lib/hash19.rb +0 -0
- data/spec/hash19/access_spec.rb +0 -0
- data/spec/hash19/associations_spec.rb +0 -0
- data/spec/hash19/contains_spec.rb +0 -0
- data/spec/hash19/core_spec.rb +0 -0
- data/spec/hash19/future_spec.rb +0 -0
- data/spec/hash19/injection_spec.rb +0 -0
- data/spec/spec_helper.rb +2 -0
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04b9042abb5650e9ee4e247e0c3539b6c5acf2f2
|
4
|
+
data.tar.gz: dbf0b31e2185441e35994eb2635dc3283e301edb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1baa6df02fbd4ad2e90ae39ebc36cfdf9db31f4302a0664864275b24d975c46bd9056ed9137d91fed65430a5a4e9148733dbf2e9e1aa8326653fd76e1523a2ba
|
7
|
+
data.tar.gz: 902ca441b549ff9a037fd80dbf755acbf0e8309d3d198632f086d2e6cf32732244c99bdb59d098e4f65d8a31427da8505de38420ddcda9927d3a4b2e39b6292b
|
data/.gitignore
CHANGED
File without changes
|
data/.ruby-gemset
CHANGED
File without changes
|
data/.ruby-version
CHANGED
File without changes
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
File without changes
|
data/LICENSE.txt
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Hash19
|
2
2
|
[![Build Status](https://travis-ci.org/rcdexta/hash19.svg)](https://travis-ci.org/rcdexta/hash19)
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/hash19.svg)](http://badge.fury.io/rb/hash19)
|
4
|
+
[![Coverage Status](https://img.shields.io/coveralls/rcdexta/hash19.svg)](https://coveralls.io/r/rcdexta/hash19)
|
3
5
|
|
4
6
|
![Hash-19](https://s3-us-west-1.amazonaws.com/rcdexta/hash-19-droid.png)
|
5
7
|
|
@@ -7,6 +9,8 @@
|
|
7
9
|
|
8
10
|
Ahem.. Ahem.. So about this gem itself.. When I was writing an aggregation API that had to talk to multiple services each with their own REST end-points and JSON schema, when mashing up multiple hashes and transforming it to a structure acceptable to the consumer, I ended up writing lot of boiler plate code. I could see patterns and there was clearly scope for optimisation.
|
9
11
|
|
12
|
+
A [detailed writeup](https://medium.com/@rcdexta/hash19-a-json-aggregation-library-f2ef43d64a86) explaining the need is available for reading.
|
13
|
+
|
10
14
|
Hash19 is an attempt at offering a DSL to tame the JSON manipulation and help in dealing with common use-cases. The features include
|
11
15
|
|
12
16
|
* whitelisting attributes
|
@@ -150,9 +154,17 @@ end
|
|
150
154
|
```
|
151
155
|
If you notice the trigger, the `using` parameter denotes the attribute to use to fetch the association and the lambda passed to `trigger` will be invoked to fetch the association. This is lazy loaded, in the sense when a call is made to `.doctor` or `.to_h`, the trigger is fired.
|
152
156
|
|
157
|
+
Associations also support alternate keys and aliasing... The below code snippet illustrates use of a different key in source json, the class to use to construct the object and the alias key in the target.
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
has_one :child, key: :offspring, alias: :junior
|
161
|
+
{offspring: {name: 'Luke Skywalker'}} # will be parsed as {'junior' => {'name' => 'Luke Skywalker'}}
|
162
|
+
```
|
163
|
+
|
164
|
+
|
153
165
|
###4. Bulk Injections
|
154
166
|
|
155
|
-
Left to itself with associations, when the root JSON is a large collection with none of the associations populated in the first place, there will several triggers fired for each item in the collection. This is the HTTP equivalent of `N+1` in the ORM world. To avoid this, Hash19 supports association injections. Let's dive into an example:
|
167
|
+
Left to itself with associations, when the root JSON is a large collection with none of the associations populated in the first place, there will be several triggers fired for each item in the collection. This is the HTTP equivalent of `N+1` in the ORM world. To avoid this, Hash19 supports association injections. Let's dive into an example:
|
156
168
|
|
157
169
|
```ruby
|
158
170
|
class SuperHeroes < Hashable
|
@@ -170,13 +182,13 @@ class SuperHeroes < Hashable
|
|
170
182
|
def find_all(ids)..end #calls bulk API across wire. Implementation hidden
|
171
183
|
end
|
172
184
|
```
|
173
|
-
If you notice, `SuperHeroes` is a wrapper class around `SuperHero`. This is the object equivalent of a JSON collection. The `inject` method will extract `weapon_id` from all items in the collection and call the `trigger` and put back the resultant entities joining `superhero.weapon_id` and `weapon.id`
|
185
|
+
If you notice, `SuperHeroes` is a wrapper class around `SuperHero`. This is the object equivalent of a JSON collection. The `inject` method will extract `weapon_id` from all items in the collection based on the json-path specified by `at` and call the `trigger` and put back the resultant entities joining `superhero.weapon_id` and `weapon.id`
|
174
186
|
|
175
187
|
So, a json like below
|
176
|
-
```
|
177
|
-
|
178
|
-
|
179
|
-
|
188
|
+
```ruby
|
189
|
+
super_heros = SuperHeroes.new([{name: 'iron man', power: 'none', weapon_id: 1},
|
190
|
+
{name: 'thor', power: 'class 100', weapon_id: 2},
|
191
|
+
{name: 'hulk', power: 'bulk', weapon_id: 3}])
|
180
192
|
```
|
181
193
|
|
182
194
|
will lead to one call to `Weapon#find_all` with params `[1,2,3]` to fetch all weapon details. And the final collection will be of the form:
|
@@ -186,7 +198,7 @@ super_heroes.to_h #[{'name' => 'iron man', 'power' => 'none', 'weapon' => {'name
|
|
186
198
|
#{'name' => 'hulk', 'power' => 'bulk', 'weapon' => {'name' => 'hands', 'id' => 3}}
|
187
199
|
```
|
188
200
|
|
189
|
-
Note that `injection` always overrides the association trigger
|
201
|
+
Note that `injection` always overrides the association trigger since the former is eager loaded and latter is lazy loaded thus avoiding the `N+1` calls.
|
190
202
|
|
191
203
|
One other important thing to remember is that all the injections will happen in parallel. Hash19 uses [eldritch](https://github.com/beraboris/eldritch) gem to trigger multiple injections concurrently.
|
192
204
|
|
data/Rakefile
CHANGED
File without changes
|
data/hash19.gemspec
CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_development_dependency 'rspec'
|
24
24
|
spec.add_development_dependency 'pry'
|
25
25
|
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'coveralls'
|
26
27
|
|
27
28
|
spec.add_runtime_dependency 'jsonpath', '~> 0.5.6'
|
28
29
|
spec.add_runtime_dependency 'eldritch'
|
data/lib/hash19/core.rb
CHANGED
@@ -14,7 +14,7 @@ module Hash19
|
|
14
14
|
if payload.is_a? Array
|
15
15
|
@hash19 = payload.map do |el|
|
16
16
|
klass = resolve_class(self.class.contains_klass.to_s.camelize.singularize)
|
17
|
-
klass.send(:new, el).to_h(
|
17
|
+
klass.send(:new, el).to_h(true)
|
18
18
|
end
|
19
19
|
else
|
20
20
|
hash = payload.with_indifferent_access
|
@@ -39,7 +39,7 @@ module Hash19
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
def to_h(lazy
|
42
|
+
def to_h(lazy=false)
|
43
43
|
return @hash19 if lazy
|
44
44
|
if @hash19.is_a? Array
|
45
45
|
@hash19.map { |hash| traverse_hash(hash) }
|
data/lib/hash19/core_helpers.rb
CHANGED
File without changes
|
data/lib/hash19/lazy_value.rb
CHANGED
File without changes
|
data/lib/hash19/resolvers.rb
CHANGED
@@ -16,13 +16,13 @@ module Hash19
|
|
16
16
|
if association.present?
|
17
17
|
klass = resolve_class(class_name.singularize)
|
18
18
|
@hash19[opts[:alias] || name] = if type == :one
|
19
|
-
klass.send(:new, association).to_h(
|
19
|
+
klass.send(:new, association).to_h(true)
|
20
20
|
elsif type == :many
|
21
|
-
association.map { |hash| klass.send(:new, hash).to_h(
|
21
|
+
association.map { |hash| klass.send(:new, hash).to_h(true) }
|
22
22
|
end
|
23
23
|
else
|
24
24
|
unless opts[:trigger]
|
25
|
-
puts "warning: Association:<#{name}> is not present in #{self.class.name}.
|
25
|
+
# puts "warning: Association:<#{name}> is not present in #{self.class.name}. Probably a trigger is missing!"
|
26
26
|
next
|
27
27
|
end
|
28
28
|
puts "warning: Key:<#{opts[:using]}> not present in #{self.class.name}. Cannot map association:<#{name}>" unless @hash19.has_key? opts[:using]
|
data/lib/hash19/version.rb
CHANGED
data/lib/hash19.rb
CHANGED
File without changes
|
data/spec/hash19/access_spec.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
data/spec/hash19/core_spec.rb
CHANGED
File without changes
|
data/spec/hash19/future_spec.rb
CHANGED
File without changes
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hash19
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- RC
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: coveralls
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: jsonpath
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -158,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
172
|
version: '0'
|
159
173
|
requirements: []
|
160
174
|
rubyforge_project:
|
161
|
-
rubygems_version: 2.
|
175
|
+
rubygems_version: 2.4.5
|
162
176
|
signing_key:
|
163
177
|
specification_version: 4
|
164
178
|
summary: Hash helpers to map complex JSON to ruby objects. Handles associations and
|