halva 0.2.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +53 -8
- data/halva.gemspec +1 -1
- data/lib/halva/curie.rb +21 -0
- data/lib/halva/link.rb +12 -2
- data/lib/halva/resource.rb +20 -8
- data/lib/halva/version.rb +1 -1
- data/lib/halva.rb +1 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b7e22a105b03d70350b3e43d8c449edebf1eafc5dc348ebdc9d5247f9d9bf01
|
4
|
+
data.tar.gz: 96f911bb17f7fa41ff6ac293adb363eac38f5902f48cd08b9145a551ee554646
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf8aedb6cbddcbe4ff987ea66e0cca8840228aa5349fa6887643af6e7b248a8b64d440dde92de30ade4b7c22ef6ef4c9babeb7c781ff351d3aa0f8b56a8ee997
|
7
|
+
data.tar.gz: 7a2ff75eb11509ed050e36368b19ad4d55d8274fcd5db5588a3595bb193339f6a39c58f2d77d4909377050d410eaa9f608ef68b4d7f2772265685048e3ec7438
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,13 +1,20 @@
|
|
1
1
|
# Halva
|
2
2
|
|
3
|
-
HAL-compliant
|
3
|
+
HAL-compliant decorator
|
4
4
|
|
5
5
|
[![Ruby](https://github.com/denblackstache/halva/actions/workflows/main.yml/badge.svg)](https://github.com/denblackstache/halva/actions/workflows/main.yml) [![Gem Version](https://badge.fury.io/rb/halva.svg)](https://badge.fury.io/rb/halva)
|
6
6
|
|
7
|
-
Links
|
7
|
+
**Links**
|
8
8
|
* [HAL - Hypertext Application Language](https://stateless.co/hal_specification.html)
|
9
9
|
* [Specification Draft](https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-08)
|
10
10
|
|
11
|
+
**Goals**
|
12
|
+
|
13
|
+
* No DSL
|
14
|
+
* HAL-compliant
|
15
|
+
* Not responsible for the whole presentation layer
|
16
|
+
* Simple, extensible, self-discoverable
|
17
|
+
|
11
18
|
## Installation
|
12
19
|
|
13
20
|
Add this line to your application's Gemfile:
|
@@ -33,11 +40,25 @@ require 'halva'
|
|
33
40
|
|
34
41
|
order = Order.find(1)
|
35
42
|
Halva::Resource.from_model(order)
|
36
|
-
.embed(Halva::Resource.from_model(order.customer)
|
43
|
+
.embed(Halva::Resource.from_model(order.customer), :customer)
|
37
44
|
.link(Halva::Link.new('/orders/1', :self))
|
38
45
|
.link(Halva::Link.new('/orders/1/customer', :customer))
|
39
|
-
.
|
40
|
-
|
46
|
+
.to_h
|
47
|
+
|
48
|
+
# {
|
49
|
+
# :id => 1,
|
50
|
+
# :name => "Order Example"
|
51
|
+
# :_embedded => {
|
52
|
+
# :customer => [{
|
53
|
+
# :id => 1,
|
54
|
+
# :name => "Customer Example"
|
55
|
+
# }]
|
56
|
+
# },
|
57
|
+
# :_links => {
|
58
|
+
# :self => {:href => "/orders/1"},
|
59
|
+
# :customer => {:href => "/orders/1/customer"}
|
60
|
+
# }
|
61
|
+
# }
|
41
62
|
```
|
42
63
|
|
43
64
|
### Representing a collection
|
@@ -47,11 +68,35 @@ require 'halva'
|
|
47
68
|
|
48
69
|
orders = Order.find
|
49
70
|
Halva::Resource.from_empty_model
|
50
|
-
.embed(orders.map
|
51
|
-
|
71
|
+
.embed(orders.map do |order|
|
72
|
+
Halva::Resource.from_model(order)
|
73
|
+
.link(Halva::Link.new("/orders/#{order.id}", :self))
|
74
|
+
end, :'acme:order')
|
52
75
|
.link(Halva::Link.new('/orders?page=2', :self))
|
76
|
+
.link(Halva::Link.new('/orders?page=3', :next))
|
53
77
|
.link(Halva::Link.new('/orders?page=1', :prev))
|
54
|
-
.
|
78
|
+
.link(Halva::Curie.new('https://docs.acme.com/relations/{rel}', 'acme'))
|
79
|
+
.to_h
|
80
|
+
|
81
|
+
# {
|
82
|
+
# :_embedded => {
|
83
|
+
# :"acme:order" => [{
|
84
|
+
# :id => 1,
|
85
|
+
# :name => "Example"
|
86
|
+
# :_links => {:self => {:href => "/orders/1"} }
|
87
|
+
# }]
|
88
|
+
# },
|
89
|
+
# :_links => {
|
90
|
+
# :self => {:href => "/orders/1?page=2"},
|
91
|
+
# :next => {:href => "/orders/1?page=3"},
|
92
|
+
# :prev => {:href => "/orders/1?page=1"},
|
93
|
+
# :curies => [{
|
94
|
+
# name: 'acme',
|
95
|
+
# href: 'https://docs.acme.com/relations/{rel}',
|
96
|
+
# templated: true
|
97
|
+
# }]
|
98
|
+
# }
|
99
|
+
# }
|
55
100
|
|
56
101
|
```
|
57
102
|
|
data/halva.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ['Denis Semenenko']
|
9
9
|
spec.email = ['hypercoderx@gmail.com']
|
10
10
|
|
11
|
-
spec.summary = 'HAL-compliant
|
11
|
+
spec.summary = 'HAL-compliant decorator'
|
12
12
|
spec.homepage = 'https://github.com/denblackstache/halva'
|
13
13
|
spec.license = 'MIT'
|
14
14
|
spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
|
data/lib/halva/curie.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Halva
|
4
|
+
# Compact URI Link Object
|
5
|
+
# See [HAL Draft](https://datatracker.ietf.org/doc/html/draft-kelly-json-hal#section-8.2)
|
6
|
+
class Curie
|
7
|
+
attr_reader :relation, :href
|
8
|
+
|
9
|
+
# @param [String] href
|
10
|
+
# @param [String] name
|
11
|
+
def initialize(href, name)
|
12
|
+
@href = href
|
13
|
+
@relation = :curies
|
14
|
+
@link = Halva::Link.new(@href, @relation, { templated: true, name: name })
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_h
|
18
|
+
@link.to_h
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/halva/link.rb
CHANGED
@@ -2,10 +2,20 @@
|
|
2
2
|
|
3
3
|
module Halva
|
4
4
|
# HAL Link Object
|
5
|
-
# https://datatracker.ietf.org/doc/html/draft-kelly-json-hal#section-5
|
5
|
+
# See [HAL Draft](https://datatracker.ietf.org/doc/html/draft-kelly-json-hal#section-5)
|
6
6
|
class Link
|
7
|
-
attr_reader :relation
|
7
|
+
attr_reader :relation
|
8
8
|
|
9
|
+
# @param [String] href
|
10
|
+
# @param [Symbol] relation
|
11
|
+
# @param [Hash] options (templated, type, deprecation, name, profile, title, hreflang)
|
12
|
+
# @option options [Boolean] :templated true when the Link Object's "href" property is a URI Template
|
13
|
+
# @option options [String] :type a hint to indicate the media type expected when dereferencing the target resource
|
14
|
+
# @option options [String] :deprecation indicate that the link is to be deprecated (i.e. removed) at a future date
|
15
|
+
# @option options [String] :name a secondary key for selecting Link Objects which share the same relation type
|
16
|
+
# @option options [String] :profile a URI that hints about the profile of the target resource
|
17
|
+
# @option options [String] :title label for the link with a human-readable identifier
|
18
|
+
# @option options [String] :hreflang indicate the language of the target resource
|
9
19
|
def initialize(href, relation, options = {})
|
10
20
|
@href = href
|
11
21
|
@relation = relation.to_sym
|
data/lib/halva/resource.rb
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
module Halva
|
4
4
|
# HAL Resource object
|
5
|
-
# https://datatracker.ietf.org/doc/html/draft-kelly-json-hal#section-4
|
5
|
+
# See [HAL Draft](https://datatracker.ietf.org/doc/html/draft-kelly-json-hal#section-4)
|
6
6
|
class Resource
|
7
7
|
EMBEDDED_KEY = :_embedded
|
8
8
|
LINKS_KEY = :_links
|
9
|
+
CURIES_KEY = :curies
|
9
10
|
|
10
11
|
def self.from_model(model)
|
11
12
|
new(model.to_h)
|
@@ -16,7 +17,7 @@ module Halva
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def initialize(model)
|
19
|
-
@model = model
|
20
|
+
@model = model.freeze
|
20
21
|
@embedded = []
|
21
22
|
@links = []
|
22
23
|
end
|
@@ -31,22 +32,33 @@ module Halva
|
|
31
32
|
self
|
32
33
|
end
|
33
34
|
|
34
|
-
def
|
35
|
+
def to_h
|
36
|
+
document = @model.dup
|
35
37
|
unless @embedded.empty?
|
36
|
-
|
38
|
+
document[EMBEDDED_KEY] = {} unless document.key?(EMBEDDED_KEY)
|
37
39
|
@embedded.each do |emb|
|
38
|
-
|
40
|
+
is_collection = emb[:resource].is_a?(Enumerable)
|
41
|
+
document[EMBEDDED_KEY][emb[:relation]] = if is_collection
|
42
|
+
emb[:resource].map(&:to_h)
|
43
|
+
else
|
44
|
+
emb[:resource].to_h
|
45
|
+
end
|
39
46
|
end
|
40
47
|
end
|
41
48
|
|
42
49
|
unless @links.empty?
|
43
|
-
|
50
|
+
document[LINKS_KEY] = {} unless document.key?(LINKS_KEY)
|
44
51
|
@links.each do |link|
|
45
|
-
|
52
|
+
if link.relation == CURIES_KEY
|
53
|
+
document[LINKS_KEY][CURIES_KEY] = [] unless document[LINKS_KEY].key?(CURIES_KEY)
|
54
|
+
document[LINKS_KEY][CURIES_KEY] << link.to_h
|
55
|
+
else
|
56
|
+
document[LINKS_KEY][link.relation] = link.to_h
|
57
|
+
end
|
46
58
|
end
|
47
59
|
end
|
48
60
|
|
49
|
-
|
61
|
+
document
|
50
62
|
end
|
51
63
|
end
|
52
64
|
end
|
data/lib/halva/version.rb
CHANGED
data/lib/halva.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: halva
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Semenenko
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-02-
|
11
|
+
date: 2023-02-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- bin/setup
|
31
31
|
- halva.gemspec
|
32
32
|
- lib/halva.rb
|
33
|
+
- lib/halva/curie.rb
|
33
34
|
- lib/halva/link.rb
|
34
35
|
- lib/halva/resource.rb
|
35
36
|
- lib/halva/version.rb
|
@@ -58,5 +59,5 @@ requirements: []
|
|
58
59
|
rubygems_version: 3.1.6
|
59
60
|
signing_key:
|
60
61
|
specification_version: 4
|
61
|
-
summary: HAL-compliant
|
62
|
+
summary: HAL-compliant decorator
|
62
63
|
test_files: []
|