hal_decorator 0.2.1 → 0.3.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
  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