yaks 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|