hal_decorator 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2897e8bc0d974babfc03d1461b90ae41c9e082a7
4
- data.tar.gz: d2205bd5adc36fb326f2e90571e5f7b5ea02fd2b
3
+ metadata.gz: 17e8c82477966a527d6a2f9d51120641f2b6bb11
4
+ data.tar.gz: 8a4043e183c059f458c5495cb4eb287e7b3e6278
5
5
  SHA512:
6
- metadata.gz: 78f1ff66a8dee4282b2286cb7fdb96d56d48a498eb43f00d1606b8362d7d5597d58ce6eddf82fd8f2d513865fc1a969c01588cced3855c962c764ec3e97c76e9
7
- data.tar.gz: 22b1031407abe3fc434add985e476c1d7281f56884e22162325694b052f8e7d48184e879fac68654da845c1c405f212d8c4bfd5e7b3ac591587e74dddf2f21c7
6
+ metadata.gz: 674b6c85ae4dc3b1498bb0386d24903504aa7a026a2fc6592891c098117b08ba2f7c696ce26161ddf88009bed66c02e9d5dcfe18c74ead3a7d9f430515ce05d2
7
+ data.tar.gz: 5ad6702a98818ab1fde31b646cb77b766cc60688dfc5858bf3105a43cbcda1db6509d6f1d4506ff89f9fae18801f2d7464c1fc6e241c7be2a04dff5f39f4531d
checksums.yaml.gz.sig CHANGED
Binary file
@@ -3,15 +3,25 @@ require 'hal_decorator/property'
3
3
  module HALDecorator
4
4
  module Attributes
5
5
  def attribute(*args, &block)
6
- @_attributes ||= []
6
+ @_attributes ||= init_attributes
7
+ @_attributes = @_attributes.reject { |attr| attr.name == args.first }
7
8
  @_attributes << Property.new(*args, &block)
8
9
  end
9
10
 
10
11
  protected
11
12
 
12
13
  def attributes
13
- @_attributes ||= []
14
- @_attributes.dup
14
+ @_attributes ||= init_attributes
15
+ end
16
+
17
+ private
18
+
19
+ def init_attributes
20
+ return [] unless is_a? Class
21
+ return [] unless superclass.respond_to?(:attributes, true)
22
+ superclass.attributes.each do |attr|
23
+ attr.change_scope(self)
24
+ end
15
25
  end
16
26
  end
17
27
  end
@@ -3,8 +3,6 @@ require 'hal_decorator/property'
3
3
  module HALDecorator
4
4
  module Collection
5
5
 
6
- attr_reader :collection_name
7
-
8
6
  class CollectionParameters
9
7
  include Attributes
10
8
  include Links
@@ -25,7 +23,16 @@ module HALDecorator
25
23
  protected
26
24
 
27
25
  def collection_parameters
28
- @_parameters ||= nil
26
+ @_parameters ||= init_collection_params
27
+ end
28
+
29
+ private
30
+
31
+ def init_collection_params
32
+ return unless is_a? Class
33
+ if superclass.respond_to?(:collection_parameters, true)
34
+ superclass.collection_parameters
35
+ end
29
36
  end
30
37
  end
31
38
  end
@@ -6,15 +6,25 @@ module HALDecorator
6
6
  if value.nil? && !block_given?
7
7
  raise 'curie must be called with non nil value or be given a block'
8
8
  end
9
- @_curies ||= []
9
+ @_curies ||= init_curies
10
+ @_curies = @_curies.reject { |curie| curie.name == rel }
10
11
  @_curies << Property.new(rel, value, &block)
11
12
  end
12
13
 
13
14
  protected
14
15
 
15
16
  def curies
16
- @_curies ||= []
17
- @_curies.dup
17
+ @_curies ||= init_curies
18
+ end
19
+
20
+ private
21
+
22
+ def init_curies
23
+ return [] unless is_a? Class
24
+ return [] unless superclass.respond_to?(:curies, true)
25
+ superclass.curies.each do |curie|
26
+ curie.change_scope(self)
27
+ end
18
28
  end
19
29
  end
20
30
  end
@@ -2,6 +2,10 @@ require 'json'
2
2
 
3
3
  module HALDecorator
4
4
 
5
+ def self.from_hal(decorator, payload, resource = nil)
6
+ decorator.from_hal(payload, resource)
7
+ end
8
+
5
9
  module Deserializer
6
10
 
7
11
  class Error < StandardError; end
@@ -12,15 +12,25 @@ module HALDecorator
12
12
  end
13
13
 
14
14
  def embed(*args, &block)
15
- @_embedded ||= []
15
+ @_embedded ||= init_embedded
16
+ @_embedded = @_embedded.reject { |embed| embed.name == args.first }
16
17
  @_embedded << Embed.new(*args, &block)
17
18
  end
18
19
 
19
20
  protected
20
21
 
21
22
  def embedded
22
- @_embedded ||= []
23
- @_embedded.dup
23
+ @_embedded ||= init_embedded
24
+ end
25
+
26
+ private
27
+
28
+ def init_embedded
29
+ return [] unless is_a? Class
30
+ return [] unless superclass.respond_to?(:embedded, true)
31
+ superclass.embedded.each do |embed|
32
+ embed.change_scope(self)
33
+ end
24
34
  end
25
35
  end
26
36
  end
@@ -1,6 +1,17 @@
1
1
  require 'hal_decorator/property'
2
2
 
3
3
  module HALDecorator
4
+
5
+ def self.base_href=(base)
6
+ @base_href = base&.sub(%r(/*$), '')
7
+ end
8
+
9
+ def self.href(href)
10
+ return href if (@base_href ||= '').empty?
11
+ return href if href =~ %r(\A(\w+://)?[^/])
12
+ @base_href + href
13
+ end
14
+
4
15
  module Links
5
16
 
6
17
  class Link < HALDecorator::Property
@@ -12,18 +23,32 @@ module HALDecorator
12
23
  @http_method = http_method
13
24
  super(rel, value, &block)
14
25
  end
26
+
27
+ def rel
28
+ name
29
+ end
15
30
  end
16
31
 
17
32
  def link(rel, value = nil, method: nil, methods: nil, &block)
18
- @_links ||= []
33
+ @_links ||= init_links
34
+ @_links = @_links.reject { |link| link.rel == rel }
19
35
  @_links << Link.new(rel, value, http_method: method || methods, &block)
20
36
  end
21
37
 
22
38
  protected
23
39
 
24
40
  def links
25
- @_links ||= []
26
- @_links.dup
41
+ @_links ||= init_links
42
+ end
43
+
44
+ private
45
+
46
+ def init_links
47
+ return [] unless is_a? Class
48
+ return [] unless superclass.respond_to?(:links, true)
49
+ superclass.links.each do |link|
50
+ link.change_scope(self)
51
+ end
27
52
  end
28
53
  end
29
54
  end
@@ -14,7 +14,7 @@ module HALDecorator
14
14
  end
15
15
 
16
16
  def HALDecorator.lookup_decorator(model)
17
- clazz = model.class == Class ? model : model.class
17
+ clazz = model.is_a?(Class) ? model : model.class
18
18
  decorators = @decorators.select { |d, m| m == clazz }.keys.compact
19
19
  decorators.empty? ? nil : decorators
20
20
  end
@@ -23,6 +23,13 @@ module HALDecorator
23
23
  def model(clazz)
24
24
  HALDecorator.register(model: clazz, decorator: self)
25
25
  end
26
+
27
+ def inherited(subclass)
28
+ if model = HALDecorator.lookup_model(self)
29
+ HALDecorator.register(model: model, decorator: subclass)
30
+ end
31
+ super
32
+ end
26
33
  end
27
34
  end
28
35
 
@@ -16,7 +16,7 @@ module HALDecorator
16
16
  def value(resource = nil, options = {})
17
17
  @resource = resource
18
18
  @options = options
19
- if @scope
19
+ if scope
20
20
  value_from_block
21
21
  elsif resource && @value.nil?
22
22
  resource.public_send(name) if resource.respond_to?(name)
@@ -27,21 +27,28 @@ module HALDecorator
27
27
  reset
28
28
  end
29
29
 
30
+ def change_scope(new_scope)
31
+ return unless scope
32
+ @scope = new_scope
33
+ end
34
+
30
35
  def method_missing(method, *args, &block)
31
- if @scope&.respond_to? method
32
- define_singleton_method(method) { |*a, &b| @scope.public_send method, *a, &b }
36
+ if scope&.respond_to? method
37
+ define_singleton_method(method) { |*a, &b| scope.public_send method, *a, &b }
33
38
  return public_send(method, *args, &block)
34
39
  end
35
40
  super
36
41
  end
37
42
 
38
43
  def respond_to_missing?(method, include_private = false)
39
- return true if @scope&.respond_to? method
44
+ return true if scope&.respond_to? method
40
45
  super
41
46
  end
42
47
 
43
48
  private
44
49
 
50
+ attr_reader :scope
51
+
45
52
  def reset
46
53
  @resource = nil
47
54
  @options = nil
@@ -0,0 +1,41 @@
1
+ require 'hal_decorator/property'
2
+
3
+ module HALDecorator
4
+ module SerializeHooks
5
+
6
+ class Hook
7
+ attr_reader :name, :resource, :options
8
+
9
+ def initialize(&block)
10
+ @block = block
11
+ end
12
+
13
+ def run(resource, options, arg)
14
+ @resource = resource
15
+ @options = options
16
+ instance_exec(arg, &@block) if @block
17
+ ensure
18
+ @resource = nil
19
+ @options = nil
20
+ end
21
+ end
22
+
23
+ def post_serialize(&block)
24
+ @_post_serialize_hook = Hook.new(&block)
25
+ end
26
+
27
+ protected
28
+
29
+ def post_serialize_hook
30
+ @_post_serialize_hook ||= init_post_serialize_hook
31
+ end
32
+
33
+ private
34
+
35
+ def init_post_serialize_hook
36
+ return unless is_a? Class
37
+ return unless superclass.respond_to?(:post_serialize_hook, true)
38
+ superclass.post_serialize_hook
39
+ end
40
+ end
41
+ end
@@ -2,6 +2,22 @@ require 'json'
2
2
 
3
3
  module HALDecorator
4
4
 
5
+ def self.to_hal(resource, options = {})
6
+ raise Serializer::Error, "Resource is nil" if resource.nil?
7
+ decorator = options.delete(:decorator)
8
+ decorator ||= HALDecorator.lookup_decorator(resource)&.last
9
+ raise Serializer::Error, "No decorator for #{resource}" unless decorator
10
+ decorator.to_hal(resource, options)
11
+ end
12
+
13
+ def self.to_collection(resources, options = {})
14
+ raise Serializer::Error, "resources is nil" if resources.nil?
15
+ decorator = options.delete(:decorator)
16
+ decorator ||= HALDecorator.lookup_decorator(resources.first)&.last
17
+ raise Serializer::Error, "No decorator for #{resources.first}" unless decorator
18
+ decorator.to_collection(resources, options)
19
+ end
20
+
5
21
  module Serializer
6
22
 
7
23
  class Error < StandardError; end
@@ -30,56 +46,64 @@ module HALDecorator
30
46
 
31
47
  protected
32
48
 
33
- def to_hash(object, options)
49
+ def to_hash(resource, options)
34
50
  {}.tap do |serialized|
35
- serialized.merge! serialize_attributes(object, options)
36
- serialized.merge! serialize_links(object, options)
37
- serialized.merge! serialize_embedded(object, options)
51
+ serialized.merge! serialize_attributes(resource, options)
52
+ serialized.merge! serialize_links(resource, options)
53
+ serialized.merge! serialize_embedded(resource, options)
54
+
55
+ run_post_serialize_hook!(resource, options, serialized)
38
56
  end
39
57
  end
40
58
 
41
- def serialize_attributes(object, options)
42
- _serialize_attributes(attributes, object, options)
59
+ def serialize_attributes(resource, options)
60
+ _serialize_attributes(attributes, resource, options)
61
+ end
62
+
63
+ def serialize_links(resource, options)
64
+ _serialize_links(links, curies, resource, options)
43
65
  end
44
66
 
45
- def serialize_links(object, options)
46
- _serialize_links(links, curies, object, options)
67
+ def serialize_curies(resource, options)
68
+ _serialize_curies(curies, resource, options)
47
69
  end
48
70
 
49
- def serialize_curies(object, options)
50
- _serialize_curies(curies, object, options)
71
+ def serialize_embedded(resource, options)
72
+ _serialize_embedded(embedded, resource, options)
51
73
  end
52
74
 
53
- def serialize_embedded(object, options)
54
- _serialize_embedded(embedded, object, options)
75
+ def run_post_serialize_hook!(resource, options, serialized)
76
+ hook = post_serialize_hook
77
+ hook&.run(resource, options, serialized)
55
78
  end
56
79
 
57
80
  private
58
81
 
59
- def _serialize_attributes(attributes, object, options)
82
+ def _serialize_attributes(attributes, resource, options)
60
83
  attributes.each_with_object({}) do |attribute, hash|
61
- hash[attribute.name] = attribute.value(object, options)
84
+ hash[attribute.name] = attribute.value(resource, options)
62
85
  end
63
86
  end
64
87
 
65
- def _serialize_links(links, curies, object, options)
88
+ def _serialize_links(links, curies, resource, options)
66
89
  serialized = links.each_with_object({}) do |link, hash|
67
- value = link.value(object, options) or next
68
- hash[link.name] = { href: value }.tap do |s|
90
+ href = link.value(resource, options) or next
91
+ hash[link.rel] = { href: HALDecorator.href(href) }.tap do |s|
69
92
  s[:method] = link.http_method if link.http_method
70
93
  end
71
94
  end
72
- curies = _serialize_curies(curies, object, options)
95
+ curies = _serialize_curies(curies, resource, options)
73
96
  serialized[:curies] = curies if curies.any?
74
97
  return {} if serialized.empty?
75
98
  { _links: serialized }
76
99
  end
77
100
 
78
- def _serialize_curies(curies, object, options)
101
+ def _serialize_curies(curies, resource, options)
79
102
  curies.each_with_object([]) do |curie, array|
103
+ href = curie.value(resource, options) or next
80
104
  array << {
81
105
  name: curie.name,
82
- href: curie.value(object, options),
106
+ href: HALDecorator.href(href),
83
107
  templated: true
84
108
  }
85
109
  end
data/lib/hal_decorator.rb CHANGED
@@ -6,42 +6,16 @@ require 'hal_decorator/model'
6
6
  require 'hal_decorator/serializer'
7
7
  require 'hal_decorator/deserializer'
8
8
  require 'hal_decorator/collection'
9
-
9
+ require 'hal_decorator/serialize_hooks'
10
10
 
11
11
  module HALDecorator
12
-
13
- def self.included(base)
14
- base.extend ClassMethods
15
- end
16
-
17
- module ClassMethods
18
- include HALDecorator::Attributes
19
- include HALDecorator::Links
20
- include HALDecorator::Curies
21
- include HALDecorator::Embedded
22
- include HALDecorator::Collection
23
- include HALDecorator::Model
24
- include HALDecorator::Serializer
25
- include HALDecorator::Deserializer
26
- end
27
-
28
- def self.to_hal(resource, options = {})
29
- raise Serializer::Error, "Resource is nil" if resource.nil?
30
- decorator = options.delete(:decorator)
31
- decorator ||= HALDecorator.lookup_decorator(resource)&.first
32
- raise Serializer::Error, "No decorator for #{resource}" unless decorator
33
- decorator.to_hal(resource, options)
34
- end
35
-
36
- def self.to_collection(resources, options = {})
37
- raise Serializer::Error, "resources is nil" if resources.nil?
38
- decorator = options.delete(:decorator)
39
- decorator ||= HALDecorator.lookup_decorator(resources.first)&.first
40
- raise Serializer::Error, "No decorator for #{resources.first}" unless decorator
41
- decorator.to_collection(resources, options)
42
- end
43
-
44
- def self.from_hal(decorator, payload, resource = nil)
45
- decorator.from_hal(payload, resource)
46
- end
12
+ include HALDecorator::Attributes
13
+ include HALDecorator::Links
14
+ include HALDecorator::Curies
15
+ include HALDecorator::Embedded
16
+ include HALDecorator::Collection
17
+ include HALDecorator::SerializeHooks
18
+ include HALDecorator::Model
19
+ include HALDecorator::Serializer
20
+ include HALDecorator::Deserializer
47
21
  end
data.tar.gz.sig CHANGED
@@ -1,2 +1 @@
1
- ����wBI8�������"t^�uc�=,��� ������Z�F�#�$L��*���%�e��k�†�X������ƥŪ�� �3���N�. V7�\��� F��ӏ�����P��jv#.n1H��l2@p��Y��$)4�I3��G��Q�d��>�|��*���$8h}&5oOZ��K������ *�ɐ�a?�*��=�P[�:[�o
2
- � ��܊���̜�Ш������MVj#�TA�
1
+ �^�^��YN܅�@�B�n@d�S�`��� $� "��&�&0fH
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hal_decorator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sammy Henningsson
@@ -31,7 +31,7 @@ cert_chain:
31
31
  CNZdF8Vavp6xMQbPHZwqjaeZz2WRXYS7jyYSvCunjwa3OtvXtfbIEGEWE6IM+t9k
32
32
  H1g6Q+B6qk9O6g==
33
33
  -----END CERTIFICATE-----
34
- date: 2017-07-27 00:00:00.000000000 Z
34
+ date: 2017-08-29 00:00:00.000000000 Z
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
@@ -130,6 +130,7 @@ files:
130
130
  - lib/hal_decorator/links.rb
131
131
  - lib/hal_decorator/model.rb
132
132
  - lib/hal_decorator/property.rb
133
+ - lib/hal_decorator/serialize_hooks.rb
133
134
  - lib/hal_decorator/serializer.rb
134
135
  homepage: https://github.com/sammyhenningsson/hal_decorator
135
136
  licenses:
metadata.gz.sig CHANGED
Binary file