hal_presenter 0.6.0 → 1.0.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: 1e7545934daa7962d7706b4e7bc60cb78c9cd75375f6ff32a09618229b3df767
4
- data.tar.gz: 042d67754faeb73d9bac72067f478c9bf1ce62053e32eb380b9c37e8c22c8147
3
+ metadata.gz: 2fe4271a7912587144464a955caafd6d5391f34b6f2ed3a41f5daa5249a39eeb
4
+ data.tar.gz: c17ab721cbbd1ff37ae96fa921a3a3bb1d003f67943c13863058dfda60a42e4d
5
5
  SHA512:
6
- metadata.gz: 89e17c89c666b5f284c69fa9c0d8bc114270e138c03942cdd0c5046220b97525e5e6ac24e3cbaeab176ac703cab96f9e7dd1df7a87e9597490bc52ccdc38b469
7
- data.tar.gz: febb52acd4490e3527caa92bdb6b82b90701efe734f6474e5e4464786bf413c7ad9c8e84488bb17ec5241cecf60aae412bd68459b1a2a8a0f192b2077ca2f252
6
+ metadata.gz: b0d7657cdb1609fe0a9e9a072be80ef61b9f9b8df31750575d9cbe007fdef6f86668b4a4c84431c1b94e04165195704eaced191443b8eaa7a3d91909f8b5bcc8
7
+ data.tar.gz: 9dac165e3f659f3e36c7d1e3f3ec8af60cb74e93152f5f68361b1b13037157fac157d0b5a40e92a60425a2b6c686f2c46a47a43a5da001bbe3efb8d022a4de28
checksums.yaml.gz.sig CHANGED
@@ -1,3 +1,3 @@
1
- =����:�fZ�f����3��J7���rS�`g���v"M��+��sfԏV�٢��E��ώ�&^�'�0�p�45զ�����r1hy�<J�����*t����x��(G�"�+)G��aC�^ {�]M
2
- U��)<=T�k,�bLc���+^Dm'9B�m�Ҋ4.|z9�zNfԦR_��~z�Юg�Υ#]y��˷*��]bod��dJ�k��lve�L
3
- 9���GIMה;A%}~
1
+ Sp�gLP@b ��ܘ��Lb���šד��y����� 6��n��K��B}���`V0���3FX:���}��� �tT�a���ݷ<C���� #��@�t<�";�#�
2
+ PӦ���[@���ib ���z��1̢��>���L�
3
+ ������ئ�R������-nv;:L};���c�({f���ІXɲ�
@@ -3,7 +3,7 @@ require 'hal_presenter/property'
3
3
  module HALPresenter
4
4
  module Attributes
5
5
  def attribute(*args, **kw_args, &block)
6
- @_attributes ||= init_attributes
6
+ @_attributes ||= __init_attributes
7
7
  @_attributes = @_attributes.reject { |attr| attr.name == args.first }
8
8
  @_attributes << Property.new(*args, **kw_args, &block)
9
9
  end
@@ -11,16 +11,16 @@ module HALPresenter
11
11
  protected
12
12
 
13
13
  def attributes
14
- @_attributes ||= init_attributes
14
+ @_attributes ||= __init_attributes
15
15
  end
16
16
 
17
17
  private
18
18
 
19
- def init_attributes
19
+ def __init_attributes
20
20
  return [] unless Class === self
21
21
  return [] unless superclass.respond_to?(:attributes, true)
22
22
  superclass.attributes.each do |attr|
23
- attr.change_scope(self)
23
+ attr.change_context(self)
24
24
  end
25
25
  end
26
26
  end
@@ -37,7 +37,7 @@ module HALPresenter
37
37
  protected
38
38
 
39
39
  def collection_properties
40
- @_collection_properties ||= init_collection_params
40
+ @_collection_properties ||= __init_collection_params
41
41
  end
42
42
 
43
43
  def can_serialize_collection?
@@ -46,7 +46,7 @@ module HALPresenter
46
46
 
47
47
  private
48
48
 
49
- def init_collection_params
49
+ def __init_collection_params
50
50
  return unless Class === self
51
51
  if superclass.respond_to?(:collection_properties, true)
52
52
  superclass.collection_properties
@@ -2,28 +2,41 @@ require 'hal_presenter/property'
2
2
 
3
3
  module HALPresenter
4
4
  module Curies
5
- def curie(rel, value = nil, **kw_args, &block)
5
+ class Curie < HALPresenter::Property
6
+ def to_h(resource = nil, options = {})
7
+ href = value(resource, options)
8
+ return {} unless href
9
+
10
+ {
11
+ name: name,
12
+ href: HALPresenter.href(href),
13
+ templated: true
14
+ }
15
+ end
16
+ end
17
+
18
+ def curie(rel, value = nil, embed_depth: nil, &block)
6
19
  if value.nil? && !block_given?
7
20
  raise 'curie must be called with non nil value or be given a block'
8
21
  end
9
- @_curies ||= init_curies
22
+ @_curies ||= __init_curies
10
23
  @_curies = @_curies.reject { |curie| curie.name == rel }
11
- @_curies << Property.new(rel, value, **kw_args, &block)
24
+ @_curies << Curie.new(rel, value, embed_depth: embed_depth, &block)
12
25
  end
13
26
 
14
27
  protected
15
28
 
16
29
  def curies
17
- @_curies ||= init_curies
30
+ @_curies ||= __init_curies
18
31
  end
19
32
 
20
33
  private
21
34
 
22
- def init_curies
35
+ def __init_curies
23
36
  return [] unless Class === self
24
37
  return [] unless superclass.respond_to?(:curies, true)
25
38
  superclass.curies.each do |curie|
26
- curie.change_scope(self)
39
+ curie.change_context(self)
27
40
  end
28
41
  end
29
42
  end
@@ -12,7 +12,7 @@ module HALPresenter
12
12
  end
13
13
 
14
14
  def embed(*args, **kw_args, &block)
15
- @_embedded ||= init_embedded
15
+ @_embedded ||= __init_embedded
16
16
  @_embedded = @_embedded.reject { |embed| embed.name == args.first }
17
17
  @_embedded << Embed.new(*args, **kw_args, &block)
18
18
  end
@@ -20,16 +20,16 @@ module HALPresenter
20
20
  protected
21
21
 
22
22
  def embedded
23
- @_embedded ||= init_embedded
23
+ @_embedded ||= __init_embedded
24
24
  end
25
25
 
26
26
  private
27
27
 
28
- def init_embedded
28
+ def __init_embedded
29
29
  return [] unless Class === self
30
30
  return [] unless superclass.respond_to?(:embedded, true)
31
31
  superclass.embedded.each do |embed|
32
- embed.change_scope(self)
32
+ embed.change_context(self)
33
33
  end
34
34
  end
35
35
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HALPresenter
4
+ class LazyEvaluator
5
+ attr_reader :resource, :options
6
+ alias resources resource
7
+
8
+ def initialize(block)
9
+ @__context = eval 'self', block.binding
10
+ define_singleton_method(:evaluate_block, &block)
11
+ end
12
+
13
+ def update_context(context)
14
+ @__context = context
15
+ end
16
+
17
+ def evaluate(resource, options)
18
+ @resource = resource
19
+ @options = options || {}
20
+ evaluate_block
21
+ ensure
22
+ @resource = nil
23
+ @options = nil
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :__context
29
+
30
+ def method_missing(method, *args, &block)
31
+ return super unless __context.respond_to?(method)
32
+
33
+ define_singleton_method(method) do |*a, &b|
34
+ __context.public_send(method, *a, &b)
35
+ end
36
+
37
+ public_send(method, *args, &block)
38
+ end
39
+
40
+ def respond_to_missing?(method, _include_private = false)
41
+ __context.respond_to?(method) || super
42
+ end
43
+ end
44
+ end
@@ -15,39 +15,59 @@ module HALPresenter
15
15
  module Links
16
16
 
17
17
  class Link < HALPresenter::Property
18
- attr_reader :http_method
19
- def initialize(rel, value = nil, **kw_args, &block)
18
+ attr_reader :type, :deprecation, :profile, :title
19
+ attr_accessor :templated
20
+
21
+ def initialize(rel, value = nil, **kwargs, &block)
20
22
  if value.nil? && !block_given?
21
23
  raise 'link must be called with non nil value or be given a block'
22
24
  end
23
- @http_method = kw_args.delete(:method) || kw_args.delete(:methods)
24
- super(rel, value, **kw_args, &block)
25
+ @type = kwargs[:type]
26
+ @deprecation = kwargs[:deprecation]
27
+ @profile = kwargs[:profile]
28
+ @title = kwargs[:title]
29
+ super(rel, value, embed_depth: kwargs[:embed_depth], &block)
25
30
  end
26
31
 
27
32
  def rel
28
33
  name
29
34
  end
35
+
36
+ def to_h(resource = nil, options = {})
37
+ href = value(resource, options)
38
+ return {} unless href
39
+
40
+ hash = {href: HALPresenter.href(href)}.tap do |h|
41
+ h[:type] = type if type
42
+ h[:deprecation] = deprecation if deprecation
43
+ h[:profile] = profile if profile
44
+ h[:title] = title if title
45
+ h[:templated] = templated if templated
46
+ end
47
+
48
+ {rel => hash}
49
+ end
30
50
  end
31
51
 
32
- def link(rel, value = nil, **kw_args, &block)
33
- @_links ||= init_links
52
+ def link(rel, value = nil, **kwargs, &block)
53
+ @_links ||= __init_links
34
54
  @_links = @_links.reject { |link| link.rel == rel }
35
- @_links << Link.new(rel, value, **kw_args, &block)
55
+ @_links << Link.new(rel, value, **kwargs, &block)
36
56
  end
37
57
 
38
58
  protected
39
59
 
40
60
  def links
41
- @_links ||= init_links
61
+ @_links ||= __init_links
42
62
  end
43
63
 
44
64
  private
45
65
 
46
- def init_links
66
+ def __init_links
47
67
  return [] unless Class === self
48
68
  return [] unless superclass.respond_to?(:links, true)
49
69
  superclass.links.each do |link|
50
- link.change_scope(self)
70
+ link.change_context(self)
51
71
  end
52
72
  end
53
73
  end
@@ -8,12 +8,12 @@ module HALPresenter
8
8
  protected
9
9
 
10
10
  def policy_class
11
- @_policy ||= init_policy
11
+ @_policy ||= __init_policy
12
12
  end
13
13
 
14
14
  private
15
15
 
16
- def init_policy
16
+ def __init_policy
17
17
  return unless Class === self
18
18
  return unless superclass.respond_to?(:policy_class, true)
19
19
  superclass.policy_class
@@ -1,58 +1,30 @@
1
+ require 'hal_presenter/lazy_evaluator'
2
+
1
3
  module HALPresenter
2
4
  class Property
3
- attr_reader :name, :resource, :embed_depth, :options
4
5
 
5
- alias :resources :resource
6
+ attr_reader :name, :embed_depth
6
7
 
7
8
  def initialize(name, value = nil, embed_depth: nil, &block)
8
- @name = name
9
+ @name = name.to_sym
9
10
  @value = value
10
11
  @embed_depth = embed_depth
11
- @scope = nil
12
- return unless block_given?
13
- @scope = eval 'self', block.binding
14
- define_singleton_method(:value_from_block, &block)
12
+ @lazy = block_given? && LazyEvaluator.new(block)
15
13
  end
16
14
 
17
- def value(resource = nil, options = {})
18
- @resource = resource
19
- @options = options
20
- if scope
21
- value_from_block
15
+ def value(resource = nil, options = nil)
16
+ if @lazy
17
+ @lazy.evaluate(resource, options)
22
18
  elsif resource && @value.nil?
23
19
  resource.public_send(name) if resource.respond_to?(name)
24
20
  else
25
21
  @value
26
22
  end
27
- ensure
28
- reset
29
- end
30
-
31
- def change_scope(new_scope)
32
- return unless scope
33
- @scope = new_scope
34
- end
35
-
36
- def method_missing(method, *args, &block)
37
- if scope&.respond_to? method
38
- define_singleton_method(method) { |*a, &b| scope.public_send method, *a, &b }
39
- return public_send(method, *args, &block)
40
- end
41
- super
42
- end
43
-
44
- def respond_to_missing?(method, include_private = false)
45
- return true if scope&.respond_to? method
46
- super
47
23
  end
48
24
 
49
- private
50
-
51
- attr_reader :scope
52
-
53
- def reset
54
- @resource = nil
55
- @options = nil
25
+ def change_context(context)
26
+ return unless @lazy
27
+ @lazy.update_context(context)
56
28
  end
57
29
  end
58
30
  end
@@ -27,12 +27,12 @@ module HALPresenter
27
27
  protected
28
28
 
29
29
  def post_serialize_hook
30
- @_post_serialize_hook ||= init_post_serialize_hook
30
+ @_post_serialize_hook ||= __init_post_serialize_hook
31
31
  end
32
32
 
33
33
  private
34
34
 
35
- def init_post_serialize_hook
35
+ def __init_post_serialize_hook
36
36
  return unless Class === self
37
37
  return unless superclass.respond_to?(:post_serialize_hook, true)
38
38
  superclass.post_serialize_hook
@@ -26,6 +26,7 @@ module HALPresenter
26
26
  def to_hal(resource = nil, options = {})
27
27
  options[:_depth] ||= 0
28
28
  hash = to_hash(resource, options)
29
+ move_curies_to_top! hash
29
30
  JSON.generate(hash)
30
31
  end
31
32
 
@@ -38,6 +39,7 @@ module HALPresenter
38
39
  options[:paginate] = HALPresenter.paginate unless options.key? :paginate
39
40
  options[:_depth] ||= 0
40
41
  hash = to_collection_hash(resources, options)
42
+ move_curies_to_top! hash
41
43
  JSON.generate(hash)
42
44
  end
43
45
 
@@ -71,6 +73,7 @@ module HALPresenter
71
73
  serialized[:_embedded] = embedded[:_embedded] || {}
72
74
 
73
75
  # Embedded resources
76
+ options[:_depth] += 1
74
77
  serialized_resources = resources.map { |resource| to_hash(resource, options) }
75
78
  serialized[:_embedded].merge!({properties.name => serialized_resources })
76
79
  end
@@ -85,20 +88,47 @@ module HALPresenter
85
88
  end
86
89
 
87
90
  def serialize_curies(resource, policy, options)
88
- _serialize_curies(curies, resource, policy, options)
91
+ _serialize_curies(curies, resource, options)
89
92
  end
90
93
 
91
94
  def serialize_embedded(resource, policy, options)
92
95
  _serialize_embedded(embedded, resource, policy, options)
93
96
  end
94
97
 
98
+ private
99
+
100
+ def move_curies_to_top!(hash)
101
+ curies = {}
102
+ find_curies(hash).each do |curie|
103
+ name = curie[:name]
104
+ curies[name] = curie
105
+ end
106
+
107
+ return if curies.empty?
108
+
109
+ hash[:_links] ||= {}
110
+ hash[:_links][:curies] = curies.values
111
+ end
112
+
113
+ def find_curies(hash)
114
+ return [] if Hash(hash).empty?
115
+
116
+ curies = hash[:_links].delete(:curies) if hash.key? :_links
117
+ curies ||= []
118
+
119
+ hash.fetch(:_embedded, {}).values.each do |embedded|
120
+ collection = embedded.is_a?(Array) ? embedded : [embedded]
121
+ collection.each { |resrc| curies += find_curies(resrc) }
122
+ end
123
+
124
+ curies
125
+ end
126
+
95
127
  def run_post_serialize_hook!(resource, options, serialized)
96
128
  hook = post_serialize_hook
97
129
  hook&.run(resource, options, serialized)
98
130
  end
99
131
 
100
- private
101
-
102
132
  def _serialize_attributes(attributes, resource, policy, options)
103
133
  attributes.each_with_object({}) do |attribute, hash|
104
134
  next unless nested_depth_ok?(attribute, options[:_depth])
@@ -111,26 +141,19 @@ module HALPresenter
111
141
  serialized = links.each_with_object({}) do |link, hash|
112
142
  next unless nested_depth_ok?(link, options[:_depth])
113
143
  next if policy && !policy.link?(link.rel)
114
- href = link.value(resource, options) or next
115
- hash[link.rel] = { href: HALPresenter.href(href) }.tap do |s|
116
- s[:method] = link.http_method if link.http_method
117
- end
144
+ hash.merge! link.to_h(resource, options)
118
145
  end
119
- curies = _serialize_curies(curies, resource, policy, options)
146
+ curies = _serialize_curies(curies, resource, options)
120
147
  serialized[:curies] = curies if curies.any?
121
148
  return {} if serialized.empty?
122
149
  { _links: serialized }
123
150
  end
124
151
 
125
- def _serialize_curies(curies, resource, policy, options)
152
+ def _serialize_curies(curies, resource, options)
126
153
  curies.each_with_object([]) do |curie, array|
127
154
  next unless nested_depth_ok?(curie, options[:_depth])
128
- href = curie.value(resource, options) or next
129
- array << {
130
- name: curie.name,
131
- href: HALPresenter.href(href),
132
- templated: true
133
- }
155
+ hash = curie.to_h(resource, options)
156
+ array << hash unless hash.empty?
134
157
  end
135
158
  end
136
159
 
@@ -179,5 +202,3 @@ module HALPresenter
179
202
  end
180
203
  end
181
204
  end
182
-
183
-
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hal_presenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sammy Henningsson
@@ -30,7 +30,7 @@ cert_chain:
30
30
  ZMhjYR7sRczGJx+GxGU2EaR0bjRsPVlC4ywtFxoOfRG3WaJcpWGEoAoMJX6Z0bRv
31
31
  M40=
32
32
  -----END CERTIFICATE-----
33
- date: 2019-02-22 00:00:00.000000000 Z
33
+ date: 2019-03-08 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rake
@@ -166,6 +166,7 @@ files:
166
166
  - lib/hal_presenter/curies.rb
167
167
  - lib/hal_presenter/deserializer.rb
168
168
  - lib/hal_presenter/embedded.rb
169
+ - lib/hal_presenter/lazy_evaluator.rb
169
170
  - lib/hal_presenter/links.rb
170
171
  - lib/hal_presenter/model.rb
171
172
  - lib/hal_presenter/pagination.rb
metadata.gz.sig CHANGED
Binary file