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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c7540c00f3cbdde45eb5601db5fa7b21fd37da8c6f9f32a12d0f7b351a01c578
4
- data.tar.gz: 858f12ed050776011ca688739717efe5ec31afc2a40940b256dfd52f0f7c15dd
3
+ metadata.gz: 3b7e22a105b03d70350b3e43d8c449edebf1eafc5dc348ebdc9d5247f9d9bf01
4
+ data.tar.gz: 96f911bb17f7fa41ff6ac293adb363eac38f5902f48cd08b9145a551ee554646
5
5
  SHA512:
6
- metadata.gz: a887b14fff4b717594cb14b43371f797ddbe2650753261a578f8eab78dd372f78b2cc9618aaed2c3214d69eda63d19b39acb60590a6c8a6353746c4dd2559028
7
- data.tar.gz: 329b6db4147b2646d7f613bacce0202cf1211af44376e7479ff8f917600a8a29c36dfb3bf7ae66a887858b300e4dd16c2d78499457ba184aaed09e8f80167ea7
6
+ metadata.gz: cf8aedb6cbddcbe4ff987ea66e0cca8840228aa5349fa6887643af6e7b248a8b64d440dde92de30ade4b7c22ef6ef4c9babeb7c781ff351d3aa0f8b56a8ee997
7
+ data.tar.gz: 7a2ff75eb11509ed050e36368b19ad4d55d8274fcd5db5588a3595bb193339f6a39c58f2d77d4909377050d410eaa9f608ef68b4d7f2772265685048e3ec7438
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- halva (0.2.0)
4
+ halva (0.4.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,13 +1,20 @@
1
1
  # Halva
2
2
 
3
- HAL-compliant serializer
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).build, :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
- .build
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 { |order| Halva::Resource.from_model(order).build })
51
- .link(Halva::Link.new('/orders?page=3', :next))
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
- .build
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 serializer'
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')
@@ -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, :href
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
@@ -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 build
35
+ def to_h
36
+ document = @model.dup
35
37
  unless @embedded.empty?
36
- @model[EMBEDDED_KEY] = {} unless @model.key?(EMBEDDED_KEY)
38
+ document[EMBEDDED_KEY] = {} unless document.key?(EMBEDDED_KEY)
37
39
  @embedded.each do |emb|
38
- @model[EMBEDDED_KEY][emb[:relation]] = emb[:resource]
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
- @model[LINKS_KEY] = {} unless @model.key?(LINKS_KEY)
50
+ document[LINKS_KEY] = {} unless document.key?(LINKS_KEY)
44
51
  @links.each do |link|
45
- @model[LINKS_KEY][link.relation] = link.to_h
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
- @model.to_h
61
+ document
50
62
  end
51
63
  end
52
64
  end
data/lib/halva/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Halva
4
- VERSION = '0.2.0'
4
+ VERSION = '0.4.0'
5
5
  end
data/lib/halva.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'halva/curie'
3
4
  require 'halva/link'
4
5
  require 'halva/resource'
5
6
  require 'halva/version'
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.2.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-21 00:00:00.000000000 Z
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 serializer
62
+ summary: HAL-compliant decorator
62
63
  test_files: []