yaks 0.4.2 → 0.4.3
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 +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +65 -5
- data/README.md +38 -8
- data/Rakefile +33 -0
- data/lib/yaks/breaking_changes.rb +22 -0
- data/lib/yaks/collection_mapper.rb +18 -21
- data/lib/yaks/collection_resource.rb +19 -5
- data/lib/yaks/config/dsl.rb +78 -0
- data/lib/yaks/config.rb +37 -63
- data/lib/yaks/default_policy.rb +27 -9
- data/lib/yaks/{serializer → format}/collection_json.rb +7 -3
- data/lib/yaks/{serializer → format}/hal.rb +14 -4
- data/lib/yaks/{serializer → format}/json_api.rb +22 -4
- data/lib/yaks/{serializer.rb → format.rb} +5 -5
- data/lib/yaks/fp/hash_updatable.rb +17 -0
- data/lib/yaks/fp/updatable.rb +15 -0
- data/lib/yaks/mapper/association.rb +24 -21
- data/lib/yaks/mapper/association_mapper.rb +42 -0
- data/lib/yaks/mapper/attribute.rb +17 -0
- data/lib/yaks/mapper/class_methods.rb +0 -1
- data/lib/yaks/mapper/config.rb +8 -28
- data/lib/yaks/mapper/has_many.rb +8 -3
- data/lib/yaks/mapper/has_one.rb +1 -1
- data/lib/yaks/mapper/link.rb +13 -13
- data/lib/yaks/mapper.rb +28 -32
- data/lib/yaks/null_resource.rb +1 -0
- data/lib/yaks/resource.rb +15 -5
- data/lib/yaks/version.rb +1 -1
- data/lib/yaks.rb +16 -10
- data/spec/acceptance/acceptance_spec.rb +16 -17
- data/spec/acceptance/json_shared_examples.rb +8 -0
- data/spec/acceptance/models.rb +2 -2
- data/spec/integration/map_to_resource_spec.rb +3 -3
- data/spec/json/confucius.collection.json +39 -0
- data/spec/json/confucius.hal.json +7 -4
- data/spec/json/confucius.json_api.json +1 -1
- data/spec/spec_helper.rb +6 -0
- data/spec/support/classes_for_policy_testing.rb +36 -0
- data/spec/support/shared_contexts.rb +1 -1
- data/spec/unit/yaks/collection_mapper_spec.rb +34 -9
- data/spec/unit/yaks/collection_resource_spec.rb +4 -4
- data/spec/unit/yaks/config/dsl_spec.rb +91 -0
- data/spec/unit/yaks/config_spec.rb +10 -6
- data/spec/unit/yaks/default_policy/derive_mapper_from_object_spec.rb +80 -0
- data/spec/unit/yaks/default_policy_spec.rb +50 -0
- data/spec/unit/yaks/{serializer → format}/hal_spec.rb +1 -1
- data/spec/unit/yaks/format/json_api_spec.rb +42 -0
- data/spec/unit/yaks/format_spec.rb +12 -0
- data/spec/unit/yaks/fp/hash_updatable_spec.rb +22 -0
- data/spec/unit/yaks/fp/updatable_spec.rb +22 -0
- data/spec/unit/yaks/mapper/association_mapper_spec.rb +60 -0
- data/spec/unit/yaks/mapper/association_spec.rb +96 -41
- data/spec/unit/yaks/mapper/attribute_spec.rb +20 -0
- data/spec/unit/yaks/mapper/class_methods_spec.rb +49 -10
- data/spec/unit/yaks/mapper/config_spec.rb +25 -50
- data/spec/unit/yaks/mapper/has_many_spec.rb +33 -5
- data/spec/unit/yaks/mapper/has_one_spec.rb +32 -17
- data/spec/unit/yaks/mapper/link_spec.rb +44 -12
- data/spec/unit/yaks/mapper_spec.rb +45 -17
- data/spec/unit/yaks/resource_spec.rb +41 -7
- data/yaks.gemspec +7 -1
- metadata +72 -21
- data/examples/hal01.rb +0 -126
- data/examples/jsonapi01.rb +0 -68
- data/examples/jsonapi02.rb +0 -62
- data/examples/jsonapi03.rb +0 -86
- data/spec/support/serializers.rb +0 -14
- data/spec/unit/yaks/serializer_spec.rb +0 -12
data/lib/yaks/default_policy.rb
CHANGED
@@ -2,17 +2,29 @@ module Yaks
|
|
2
2
|
class DefaultPolicy
|
3
3
|
include Util
|
4
4
|
|
5
|
+
# Default policy options.
|
5
6
|
DEFAULTS = {
|
6
|
-
rel_template: "rel:
|
7
|
+
rel_template: "rel:{rel}",
|
7
8
|
namespace: Kernel
|
8
9
|
}
|
9
10
|
|
11
|
+
# @!attribute [r] options
|
12
|
+
# @return [Hash]
|
10
13
|
attr_reader :options
|
11
14
|
|
15
|
+
# @param [Hash] options
|
16
|
+
# @return [Yaks::DefaultPolicy]
|
12
17
|
def initialize(options = {})
|
13
18
|
@options = DEFAULTS.merge(options)
|
14
19
|
end
|
15
20
|
|
21
|
+
# @param [Object] model
|
22
|
+
# @return [Yaks::CollectionMapper, Yaks::Mapper]
|
23
|
+
# or a subclass of Yaks::Mapper of some sort.
|
24
|
+
#
|
25
|
+
# @raise [NameError] only occurs when the model
|
26
|
+
# is anything but a collection.
|
27
|
+
#
|
16
28
|
def derive_mapper_from_object(model)
|
17
29
|
if model.respond_to? :to_ary
|
18
30
|
if m = model.first
|
@@ -26,30 +38,36 @@ module Yaks
|
|
26
38
|
return @options[:namespace].const_get(:CollectionMapper)
|
27
39
|
rescue NameError
|
28
40
|
end
|
29
|
-
|
41
|
+
CollectionMapper
|
30
42
|
else
|
31
43
|
name = model.class.name.split('::').last
|
32
44
|
@options[:namespace].const_get(name + 'Mapper')
|
33
45
|
end
|
34
46
|
end
|
35
47
|
|
48
|
+
# @param [Class] mapper_class
|
49
|
+
# @return [String]
|
36
50
|
def derive_type_from_mapper_class(mapper_class)
|
37
51
|
underscore(mapper_class.name.split('::').last.sub(/Mapper$/, ''))
|
38
52
|
end
|
39
53
|
|
54
|
+
# @param [Yaks::Mapper::Association] association
|
55
|
+
# @return [Class] of subclass Yaks::Mapper
|
56
|
+
# @raise [NameError]
|
40
57
|
def derive_mapper_from_association(association)
|
41
58
|
@options[:namespace].const_get("#{camelize(association.singular_name)}Mapper")
|
42
59
|
end
|
43
60
|
|
44
|
-
|
45
|
-
|
61
|
+
# @param [Yaks::Mapper::Association] association
|
62
|
+
# @return [String]
|
63
|
+
def derive_rel_from_association(association)
|
64
|
+
expand_rel( association.name )
|
46
65
|
end
|
47
66
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
)
|
67
|
+
# @param [String] relname
|
68
|
+
# @return [String]
|
69
|
+
def expand_rel(relname)
|
70
|
+
URITemplate.new(@options[:rel_template]).expand(rel: relname)
|
53
71
|
end
|
54
72
|
end
|
55
73
|
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
module Yaks
|
2
|
-
class
|
2
|
+
class Format
|
3
3
|
class CollectionJson < self
|
4
|
-
|
4
|
+
Format.register self, :collection_json, 'application/vnd.collection+json'
|
5
5
|
|
6
6
|
include FP
|
7
7
|
|
8
|
+
# @param [Yaks:Resource] resource
|
9
|
+
# @return [Hash]
|
8
10
|
def serialize_resource(resource)
|
9
11
|
result = {
|
10
12
|
version: "1.0",
|
@@ -14,6 +16,8 @@ module Yaks
|
|
14
16
|
{collection: result}
|
15
17
|
end
|
16
18
|
|
19
|
+
# @param [Yaks::Resource] resource
|
20
|
+
# @return [Array]
|
17
21
|
def serialize_items(resource)
|
18
22
|
resource.map do |item|
|
19
23
|
attrs = item.attributes.map do |name, value|
|
@@ -26,7 +30,7 @@ module Yaks
|
|
26
30
|
result[:href] = item.self_link.uri if item.self_link
|
27
31
|
item.links.each do |link|
|
28
32
|
next if link.rel == :self
|
29
|
-
result[:links]
|
33
|
+
result[:links] = [] unless result.key?(:links)
|
30
34
|
result[:links] << {rel: link.rel, href: link.uri}
|
31
35
|
result[:links].last[:name] = link.name if link.name
|
32
36
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
module Yaks
|
4
|
-
class
|
4
|
+
class Format
|
5
5
|
class Hal < self
|
6
|
-
|
6
|
+
Format.register self, :hal, 'application/hal+json'
|
7
7
|
|
8
8
|
protected
|
9
9
|
|
10
|
+
# @param [Yaks::Resource] resource
|
11
|
+
# @return [Hash]
|
10
12
|
def serialize_resource(resource)
|
11
13
|
# The HAL spec doesn't say explicitly how to deal missing values,
|
12
14
|
# looking at client behavior (Hyperagent) it seems safer to return an empty
|
@@ -19,14 +21,18 @@ module Yaks
|
|
19
21
|
result
|
20
22
|
end
|
21
23
|
|
24
|
+
# @param [Array] links
|
25
|
+
# @return [Hash]
|
22
26
|
def serialize_links(links)
|
23
27
|
links.reduce({}, &method(:serialize_link))
|
24
28
|
end
|
25
29
|
|
30
|
+
# @param [Hash] memo
|
31
|
+
# @param [Yaks::Resource::Link]
|
32
|
+
# @return [Hash]
|
26
33
|
def serialize_link(memo, link)
|
27
34
|
hal_link = {href: link.uri}
|
28
|
-
hal_link.merge!(link.options
|
29
|
-
hal_link.merge!(templated: true) if link.templated?
|
35
|
+
hal_link.merge!(link.options)
|
30
36
|
|
31
37
|
memo[link.rel] = if singular?(link.rel)
|
32
38
|
hal_link
|
@@ -36,10 +42,14 @@ module Yaks
|
|
36
42
|
memo
|
37
43
|
end
|
38
44
|
|
45
|
+
# @param [String] rel
|
46
|
+
# @return [Boolean]
|
39
47
|
def singular?(rel)
|
40
48
|
!options.fetch(:plural_links) { [] }.include?(rel)
|
41
49
|
end
|
42
50
|
|
51
|
+
# @param [Array] subresources
|
52
|
+
# @return [Hash]
|
43
53
|
def serialize_embedded(subresources)
|
44
54
|
subresources.each_with_object({}) do |(rel, resources), memo|
|
45
55
|
memo[rel] = if resources.collection?
|
@@ -1,12 +1,14 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
module Yaks
|
4
|
-
class
|
4
|
+
class Format
|
5
5
|
class JsonApi < self
|
6
|
-
|
6
|
+
Format.register self, :json_api, 'application/vnd.api+json'
|
7
7
|
|
8
8
|
include FP
|
9
9
|
|
10
|
+
# @param [Yaks::Resource] resource
|
11
|
+
# @return [Hash]
|
10
12
|
def call(resource)
|
11
13
|
main_collection = resource.map(&method(:serialize_resource))
|
12
14
|
|
@@ -18,6 +20,8 @@ module Yaks
|
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
23
|
+
# @param [Yaks::Resource] resource
|
24
|
+
# @return [Hash]
|
21
25
|
def serialize_resource(resource)
|
22
26
|
result = resource.attributes
|
23
27
|
|
@@ -32,24 +36,34 @@ module Yaks
|
|
32
36
|
result
|
33
37
|
end
|
34
38
|
|
39
|
+
# @param [Yaks::Resource] subresource
|
40
|
+
# @return [Hash]
|
35
41
|
def serialize_links(subresources)
|
36
|
-
subresources.each_with_object({}) do |(
|
42
|
+
subresources.each_with_object({}) do |(_name, resource), hsh|
|
37
43
|
next if resource.is_a? NullResource
|
38
44
|
key = resource.collection? ? pluralize(resource.type) : resource.type
|
39
45
|
hsh[key] = serialize_link(resource)
|
40
46
|
end
|
41
47
|
end
|
42
48
|
|
49
|
+
# @param [Yaks::Resource] resource
|
50
|
+
# @return [Array, String]
|
43
51
|
def serialize_link(resource)
|
44
52
|
resource.collection? ? resource.map(&send_with_args(:[], :id)) : resource[:id]
|
45
53
|
end
|
46
54
|
|
55
|
+
# @param [Hash] subresources
|
56
|
+
# @param [Hash] hsh
|
57
|
+
# @return [Hash]
|
47
58
|
def serialize_linked_subresources(subresources, hsh)
|
48
|
-
subresources.
|
59
|
+
subresources.values.each do |resources|
|
49
60
|
serialize_linked_resources(resources, hsh)
|
50
61
|
end
|
51
62
|
end
|
52
63
|
|
64
|
+
# @param [Array] resources
|
65
|
+
# @param [Hash] linked
|
66
|
+
# @return [Hash]
|
53
67
|
def serialize_linked_resources(resources, linked)
|
54
68
|
resources.each_with_object(linked) do |resource, memo|
|
55
69
|
serialize_subresource(resource, memo)
|
@@ -57,6 +71,10 @@ module Yaks
|
|
57
71
|
end
|
58
72
|
|
59
73
|
# {shows => [{id: 3, name: 'foo'}]}
|
74
|
+
#
|
75
|
+
# @param [Yaks::Resource] resource
|
76
|
+
# @param [Hash] linked
|
77
|
+
# @return [Hash]
|
60
78
|
def serialize_subresource(resource, linked)
|
61
79
|
key = pluralize(resource.type)
|
62
80
|
set = linked.fetch(key) { Set.new }
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Yaks
|
2
|
-
class
|
2
|
+
class Format
|
3
3
|
extend Forwardable
|
4
4
|
include Util
|
5
5
|
|
@@ -9,7 +9,7 @@ module Yaks
|
|
9
9
|
protected :links, :attributes, :subresources, :options
|
10
10
|
|
11
11
|
def initialize(options = {})
|
12
|
-
@options
|
12
|
+
@options = options
|
13
13
|
end
|
14
14
|
|
15
15
|
def call(resource)
|
@@ -19,15 +19,15 @@ module Yaks
|
|
19
19
|
|
20
20
|
class << self
|
21
21
|
def register(klass, name, mime_type)
|
22
|
-
@
|
23
|
-
@
|
22
|
+
@formats ||= {}
|
23
|
+
@formats[name] = klass
|
24
24
|
|
25
25
|
@mime_types ||= {}
|
26
26
|
@mime_types[mime_type] = [name, klass]
|
27
27
|
end
|
28
28
|
|
29
29
|
def by_name(name)
|
30
|
-
@
|
30
|
+
@formats.fetch(name)
|
31
31
|
end
|
32
32
|
|
33
33
|
def by_mime_type(mime_type)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Yaks
|
2
|
+
module FP
|
3
|
+
|
4
|
+
class HashUpdatable < Module
|
5
|
+
def initialize(*attributes)
|
6
|
+
define_method :update do |updates|
|
7
|
+
self.class.new(
|
8
|
+
attributes.each_with_object({}) {|attr, hsh|
|
9
|
+
hsh[attr] = updates.fetch(attr) { send(attr) }
|
10
|
+
}
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -1,38 +1,41 @@
|
|
1
1
|
module Yaks
|
2
2
|
class Mapper
|
3
3
|
class Association
|
4
|
-
include Equalizer.new(:name, :
|
4
|
+
include Equalizer.new(:name, :child_mapper, :rel, :href, :link_if)
|
5
|
+
include Util
|
5
6
|
|
6
|
-
attr_reader :name, :
|
7
|
+
attr_reader :name, :child_mapper, :rel, :href, :link_if
|
7
8
|
|
8
|
-
def initialize(
|
9
|
-
@name
|
10
|
-
|
9
|
+
def initialize(options)
|
10
|
+
@name = options.fetch(:name)
|
11
|
+
@child_mapper = options.fetch(:mapper, Undefined)
|
12
|
+
@rel = options.fetch(:rel, Undefined)
|
13
|
+
|
14
|
+
@href = options.fetch(:href, Undefined)
|
15
|
+
@link_if = options.fetch(:link_if, Undefined)
|
11
16
|
end
|
12
17
|
|
13
|
-
|
14
|
-
|
15
|
-
# @return Array[rel, resource]
|
16
|
-
# Returns the rel (registered type or URI) + the associated, mapped resource
|
17
|
-
def create_subresource(parent_mapper, lookup, context)
|
18
|
-
[
|
19
|
-
map_rel(parent_mapper, context.fetch(:policy)),
|
20
|
-
map_resource(lookup[name], context)
|
21
|
-
]
|
18
|
+
def add_to_resource(resource, parent_mapper, context)
|
19
|
+
AssociationMapper.new(parent_mapper, self, context).call(resource)
|
22
20
|
end
|
23
21
|
|
24
|
-
def
|
25
|
-
|
26
|
-
policy.derive_rel_from_association(parent_mapper, self)
|
22
|
+
def render_as_link?(parent_mapper)
|
23
|
+
href != Undefined && link_if != Undefined && Resolve(link_if, parent_mapper)
|
27
24
|
end
|
28
25
|
|
29
|
-
def
|
30
|
-
return
|
31
|
-
policy.
|
26
|
+
def map_rel(policy)
|
27
|
+
return rel unless rel.equal?(Undefined)
|
28
|
+
policy.derive_rel_from_association(self)
|
32
29
|
end
|
33
30
|
|
34
31
|
# @abstract
|
35
|
-
def map_resource(
|
32
|
+
def map_resource(_object, _context)
|
33
|
+
end
|
34
|
+
|
35
|
+
# support for HasOne and HasMany
|
36
|
+
def resolve_association_mapper(policy)
|
37
|
+
return child_mapper unless child_mapper.equal?(Undefined)
|
38
|
+
policy.derive_mapper_from_association(self)
|
36
39
|
end
|
37
40
|
|
38
41
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Yaks
|
2
|
+
class Mapper
|
3
|
+
class AssociationMapper
|
4
|
+
attr_reader :parent_mapper, :context, :rel, :association
|
5
|
+
|
6
|
+
def initialize(parent_mapper, association, context)
|
7
|
+
@parent_mapper = parent_mapper
|
8
|
+
@association = association
|
9
|
+
@context = context.merge(
|
10
|
+
mapper_stack: context[:mapper_stack] + [parent_mapper]
|
11
|
+
)
|
12
|
+
@rel = association.map_rel(policy)
|
13
|
+
end
|
14
|
+
|
15
|
+
def policy
|
16
|
+
context.fetch(:policy)
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(resource)
|
20
|
+
if association.render_as_link?(parent_mapper)
|
21
|
+
add_link(resource)
|
22
|
+
else
|
23
|
+
add_subresource(resource)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_link(resource)
|
28
|
+
Link.new(rel, association.href, {})
|
29
|
+
.add_to_resource(resource, parent_mapper, nil)
|
30
|
+
# Yaks::Mapper::Link doesn't do anything with the context, making it
|
31
|
+
# hard to test that we pass it a context. Passing nil for now, until
|
32
|
+
# this is actually needed and can be tested.
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_subresource(resource)
|
36
|
+
object = parent_mapper.load_association(association.name)
|
37
|
+
subresource = association.map_resource(object, context)
|
38
|
+
resource.add_subresource(rel, subresource)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Yaks
|
2
|
+
class Mapper
|
3
|
+
class Attribute
|
4
|
+
include Equalizer.new(:name)
|
5
|
+
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(name)
|
9
|
+
@name = name
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_to_resource(resource, mapper, _context)
|
13
|
+
resource.update_attributes(name => mapper.load_attribute(name))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/yaks/mapper/config.rb
CHANGED
@@ -2,6 +2,7 @@ module Yaks
|
|
2
2
|
class Mapper
|
3
3
|
class Config
|
4
4
|
include Equalizer.new(:type, :attributes, :links, :associations)
|
5
|
+
include FP::Updatable.new(:type, :attributes, :links, :associations)
|
5
6
|
|
6
7
|
attr_reader :links, :associations
|
7
8
|
|
@@ -12,31 +13,22 @@ module Yaks
|
|
12
13
|
@associations = associations
|
13
14
|
end
|
14
15
|
|
15
|
-
def updated(updates)
|
16
|
-
self.class.new(
|
17
|
-
updates.fetch(:type) { type },
|
18
|
-
updates.fetch(:attributes) { attributes },
|
19
|
-
updates.fetch(:links) { links },
|
20
|
-
updates.fetch(:associations) { associations }
|
21
|
-
)
|
22
|
-
end
|
23
|
-
|
24
16
|
def type(type = Undefined)
|
25
17
|
return @type if type.equal?(Undefined)
|
26
|
-
|
18
|
+
update(type: type)
|
27
19
|
end
|
28
20
|
|
29
21
|
def attributes(*attrs)
|
30
22
|
return @attributes if attrs.empty?
|
31
|
-
|
32
|
-
attributes: @attributes + attrs
|
33
|
-
)
|
23
|
+
update(attributes: @attributes + attrs.map(&Attribute.method(:new)))
|
34
24
|
end
|
35
25
|
|
36
26
|
def link(rel, template, options = {})
|
37
|
-
|
38
|
-
|
39
|
-
|
27
|
+
update(links: @links + [Link.new(rel, template, options)])
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_association(type, name, options)
|
31
|
+
update(associations: @associations + [type.new(options.merge(name: name))])
|
40
32
|
end
|
41
33
|
|
42
34
|
def has_one(name, options = {})
|
@@ -47,18 +39,6 @@ module Yaks
|
|
47
39
|
add_association(HasMany, name, options)
|
48
40
|
end
|
49
41
|
|
50
|
-
def add_association(type, name, options)
|
51
|
-
updated(
|
52
|
-
associations: @associations + [
|
53
|
-
type.new(
|
54
|
-
name,
|
55
|
-
options.fetch(:mapper) { Undefined },
|
56
|
-
options.fetch(:rel) { Undefined },
|
57
|
-
options.fetch(:collection_mapper) { Undefined },
|
58
|
-
)
|
59
|
-
]
|
60
|
-
)
|
61
|
-
end
|
62
42
|
end
|
63
43
|
end
|
64
44
|
end
|
data/lib/yaks/mapper/has_many.rb
CHANGED
@@ -3,11 +3,16 @@ module Yaks
|
|
3
3
|
class HasMany < Association
|
4
4
|
include Util
|
5
5
|
|
6
|
+
def initialize(options)
|
7
|
+
super
|
8
|
+
@collection_mapper = options.fetch(:collection_mapper, Undefined)
|
9
|
+
end
|
10
|
+
|
6
11
|
def map_resource(collection, context)
|
7
12
|
return NullResource.new(collection: true) if collection.nil?
|
8
|
-
policy
|
9
|
-
|
10
|
-
context
|
13
|
+
policy = context.fetch(:policy)
|
14
|
+
item_mapper = resolve_association_mapper(policy)
|
15
|
+
context = context.merge(item_mapper: item_mapper)
|
11
16
|
collection_mapper(collection, policy).new(context).call(collection)
|
12
17
|
end
|
13
18
|
|
data/lib/yaks/mapper/has_one.rb
CHANGED
data/lib/yaks/mapper/link.rb
CHANGED
@@ -30,8 +30,10 @@ module Yaks
|
|
30
30
|
|
31
31
|
def_delegators :uri_template, :expand_partial
|
32
32
|
|
33
|
-
def
|
34
|
-
|
33
|
+
def add_to_resource(resource, mapper, _context)
|
34
|
+
resource_link = map_to_resource_link(mapper)
|
35
|
+
return resource unless resource_link
|
36
|
+
resource.add_link(resource_link)
|
35
37
|
end
|
36
38
|
|
37
39
|
def rel?(rel)
|
@@ -43,13 +45,15 @@ module Yaks
|
|
43
45
|
!options.fetch(:expand) { true }.equal? true
|
44
46
|
end
|
45
47
|
|
46
|
-
# Does this link need expansion, full or partially
|
47
|
-
def expand?
|
48
|
-
options.fetch(:expand) { true }
|
49
|
-
end
|
50
|
-
|
51
48
|
def template_variables
|
52
|
-
options.fetch(:expand) {
|
49
|
+
case options.fetch(:expand) { true }
|
50
|
+
when true
|
51
|
+
uri_template.variables
|
52
|
+
when false
|
53
|
+
[]
|
54
|
+
else
|
55
|
+
options[:expand]
|
56
|
+
end.map(&:to_sym)
|
53
57
|
end
|
54
58
|
|
55
59
|
def expansion_mapping(lookup)
|
@@ -72,11 +76,7 @@ module Yaks
|
|
72
76
|
def expand_with(lookup)
|
73
77
|
return lookup[template] if template.is_a? Symbol
|
74
78
|
|
75
|
-
|
76
|
-
expand_partial(expansion_mapping(lookup)).to_s
|
77
|
-
else
|
78
|
-
template
|
79
|
-
end
|
79
|
+
expand_partial(expansion_mapping(lookup)).to_s
|
80
80
|
end
|
81
81
|
|
82
82
|
def resource_link_options(mapper)
|
data/lib/yaks/mapper.rb
CHANGED
@@ -26,39 +26,24 @@ module Yaks
|
|
26
26
|
context.fetch(:mapper_stack)
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
return NullResource.new if object.nil?
|
33
|
-
|
34
|
-
Resource.new(
|
35
|
-
type: mapper_name,
|
36
|
-
attributes: map_attributes,
|
37
|
-
links: map_links,
|
38
|
-
subresources: map_subresources
|
39
|
-
)
|
29
|
+
def self.mapper_name(policy)
|
30
|
+
config.type || policy.derive_type_from_mapper_class(self)
|
40
31
|
end
|
41
32
|
|
42
|
-
def
|
43
|
-
|
44
|
-
memo[attr] = load_attribute(attr)
|
45
|
-
end
|
33
|
+
def mapper_name
|
34
|
+
self.class.mapper_name(policy)
|
46
35
|
end
|
47
36
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
37
|
+
def call(object)
|
38
|
+
@object = object
|
39
|
+
|
40
|
+
return NullResource.new if object.nil?
|
51
41
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
self,
|
58
|
-
method(:load_association),
|
59
|
-
context.merge(mapper_stack: mapper_stack + [self])
|
60
|
-
)
|
61
|
-
memo[rel] = subresource
|
42
|
+
[ :map_attributes,
|
43
|
+
:map_links,
|
44
|
+
:map_subresources
|
45
|
+
].inject(Resource.new(type: mapper_name)) do |resource, method|
|
46
|
+
send(method, resource)
|
62
47
|
end
|
63
48
|
end
|
64
49
|
|
@@ -67,13 +52,24 @@ module Yaks
|
|
67
52
|
end
|
68
53
|
alias load_association load_attribute
|
69
54
|
|
70
|
-
|
71
|
-
|
55
|
+
private
|
56
|
+
|
57
|
+
def map_attributes(resource)
|
58
|
+
attributes.inject(resource) do |resource, attribute|
|
59
|
+
attribute.add_to_resource(resource, self, context)
|
60
|
+
end
|
72
61
|
end
|
73
62
|
|
74
|
-
def
|
75
|
-
|
63
|
+
def map_links(resource)
|
64
|
+
links.inject(resource) do |resource, mapper_link|
|
65
|
+
mapper_link.add_to_resource(resource, self, context)
|
66
|
+
end
|
76
67
|
end
|
77
68
|
|
69
|
+
def map_subresources(resource)
|
70
|
+
associations.inject(resource) do |resource, association|
|
71
|
+
association.add_to_resource( resource, self, context)
|
72
|
+
end
|
73
|
+
end
|
78
74
|
end
|
79
75
|
end
|