yaks 0.6.0.alpha.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +46 -0
- data/lib/yaks/attributes.rb +45 -0
- data/lib/yaks/collection_resource.rb +1 -45
- data/lib/yaks/config/dsl.rb +15 -6
- data/lib/yaks/config.rb +1 -1
- data/lib/yaks/configurable.rb +20 -0
- data/lib/yaks/default_policy.rb +0 -8
- data/lib/yaks/errors.rb +3 -0
- data/lib/yaks/format/hal.rb +13 -2
- data/lib/yaks/format/halo.rb +29 -0
- data/lib/yaks/mapper/association.rb +18 -13
- data/lib/yaks/mapper/association_mapper.rb +1 -1
- data/lib/yaks/mapper/attribute.rb +1 -3
- data/lib/yaks/mapper/class_methods.rb +24 -16
- data/lib/yaks/mapper/config.rb +13 -28
- data/lib/yaks/mapper/control.rb +38 -0
- data/lib/yaks/mapper/has_many.rb +4 -8
- data/lib/yaks/mapper/link.rb +10 -2
- data/lib/yaks/mapper.rb +11 -2
- data/lib/yaks/resource/control.rb +11 -0
- data/lib/yaks/resource/link.rb +1 -7
- data/lib/yaks/resource.rb +9 -13
- data/lib/yaks/runner.rb +2 -4
- data/lib/yaks/serializer.rb +12 -0
- data/lib/yaks/stateful_builder.rb +54 -0
- data/lib/yaks/version.rb +1 -1
- data/lib/yaks.rb +16 -7
- data/spec/acceptance/acceptance_spec.rb +14 -4
- data/spec/acceptance/models.rb +9 -0
- data/spec/integration/map_to_resource_spec.rb +1 -1
- data/spec/json/confucius.halo.json +80 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/shared_contexts.rb +1 -1
- data/spec/unit/yaks/attributes_spec.rb +65 -0
- data/spec/unit/yaks/collection_mapper_spec.rb +1 -1
- data/spec/unit/yaks/collection_resource_spec.rb +7 -25
- data/spec/unit/yaks/config/dsl_spec.rb +5 -0
- data/spec/unit/yaks/config_spec.rb +2 -1
- data/spec/unit/yaks/configurable_spec.rb +25 -0
- data/spec/unit/yaks/default_policy_spec.rb +1 -7
- data/spec/unit/yaks/format/collection_json_spec.rb +1 -1
- data/spec/unit/yaks/format/hal_spec.rb +2 -2
- data/spec/unit/yaks/format/html_spec.rb +5 -0
- data/spec/unit/yaks/format/json_api_spec.rb +1 -1
- data/spec/unit/yaks/format_spec.rb +1 -5
- data/spec/unit/yaks/mapper/association_mapper_spec.rb +2 -2
- data/spec/unit/yaks/mapper/association_spec.rb +27 -3
- data/spec/unit/yaks/mapper/class_methods_spec.rb +17 -1
- data/spec/unit/yaks/mapper/config_spec.rb +16 -8
- data/spec/unit/yaks/mapper/has_many_spec.rb +15 -2
- data/spec/unit/yaks/mapper/has_one_spec.rb +1 -1
- data/spec/unit/yaks/mapper/link_spec.rb +12 -2
- data/spec/unit/yaks/mapper_spec.rb +51 -22
- data/spec/unit/yaks/resource/link_spec.rb +2 -1
- data/spec/unit/yaks/resource_spec.rb +16 -9
- data/spec/unit/yaks/runner_spec.rb +22 -2
- data/spec/unit/yaks/serializer_spec.rb +20 -0
- data/spec/unit/yaks/stateful_builder_spec.rb +41 -0
- data/yaks.gemspec +1 -0
- metadata +39 -11
- data/lib/yaks/fp/hash_updatable.rb +0 -19
- data/lib/yaks/fp/updatable.rb +0 -17
- data/spec/unit/yaks/fp/hash_updatable_spec.rb +0 -22
- data/spec/unit/yaks/fp/updatable_spec.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79d98824107ec7c700f39b7776dd1ce517f3283b
|
4
|
+
data.tar.gz: 10a45b5d3b2a73054232b63b4b2d70b5dd83c87e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8766e6b07b209e32f739caaa1e965d88a1615501705f9b8e6f6d857d8d4149816aa34ab846b0e37f9605a2ee5fc5359faed766e92f6550efda42bc5d9b4f3ebb
|
7
|
+
data.tar.gz: a65eb2384e11a8d9379f558afbaadffc67fc72cfa71fdd19812c905de84884d2a91f57366475a4da636ba987052a58c6f6e4986d9feda24226b153ed108fc22a
|
data/Rakefile
CHANGED
@@ -1,3 +1,49 @@
|
|
1
1
|
load '../rakelib/shared.rake'
|
2
2
|
|
3
3
|
gem_tasks(:yaks)
|
4
|
+
|
5
|
+
|
6
|
+
task :mutant_chunked do
|
7
|
+
[
|
8
|
+
Yaks::Attributes,
|
9
|
+
Yaks::Attributes::InstanceMethods,
|
10
|
+
Yaks::CollectionMapper,
|
11
|
+
Yaks::CollectionResource,
|
12
|
+
Yaks::Config,
|
13
|
+
Yaks::Config::DSL,
|
14
|
+
Yaks::Configurable,
|
15
|
+
Yaks::Configurable::ClassMethods,
|
16
|
+
Yaks::StatefulBuilder,
|
17
|
+
Yaks::DefaultPolicy,
|
18
|
+
Yaks::FP,
|
19
|
+
Yaks::FP::Callable,
|
20
|
+
Yaks::Format,
|
21
|
+
Yaks::Format::CollectionJson,
|
22
|
+
Yaks::Format::Hal,
|
23
|
+
Yaks::Format::Halo,
|
24
|
+
Yaks::Format::JsonAPI,
|
25
|
+
Yaks::Mapper::AssociationMapper,
|
26
|
+
Yaks::Mapper::Attribute,
|
27
|
+
Yaks::Mapper::Config,
|
28
|
+
Yaks::Mapper::Control,
|
29
|
+
Yaks::Mapper::Control::Field,
|
30
|
+
Yaks::Mapper::HasOne,
|
31
|
+
Yaks::NullResource,
|
32
|
+
Yaks::Primitivize,
|
33
|
+
Yaks::Resource::Link,
|
34
|
+
Yaks::Util,
|
35
|
+
Yaks::Serializer,
|
36
|
+
Yaks::Runner,
|
37
|
+
Yaks::Resource,
|
38
|
+
Yaks::Mapper::Link,
|
39
|
+
Yaks::Mapper::HasMany,
|
40
|
+
Yaks::Mapper::ClassMethods,
|
41
|
+
Yaks::Mapper::Association,
|
42
|
+
Yaks::Mapper,
|
43
|
+
# Yaks::Format::HTML,
|
44
|
+
].each do |space|
|
45
|
+
puts space
|
46
|
+
ENV['PATTERN'] = "#{space}"
|
47
|
+
Rake::Task["mutant"].execute
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Yaks
|
2
|
+
class Attributes < Module
|
3
|
+
attr_reader :defaults, :attributes
|
4
|
+
|
5
|
+
def initialize(*attrs)
|
6
|
+
@defaults = attrs.last.instance_of?(Hash) ? attrs.pop : {}
|
7
|
+
@attributes = attrs + @defaults.keys
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(*attrs)
|
11
|
+
defaults = attrs.last.instance_of?(Hash) ? attrs.pop : {}
|
12
|
+
self.class.new(*[*(attributes+attrs), @defaults.merge(defaults)])
|
13
|
+
end
|
14
|
+
|
15
|
+
def included(descendant)
|
16
|
+
descendant.module_exec(self) do |this|
|
17
|
+
include InstanceMethods,
|
18
|
+
Anima.new(*this.attributes),
|
19
|
+
Anima::Update
|
20
|
+
|
21
|
+
this.attributes.each do |attr|
|
22
|
+
define_method attr do |value = Undefined|
|
23
|
+
if value.equal? Undefined
|
24
|
+
instance_variable_get("@#{attr}")
|
25
|
+
else
|
26
|
+
update(attr => value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
define_singleton_method(:attributes) { this }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module InstanceMethods
|
36
|
+
def initialize(attributes = {})
|
37
|
+
super(self.class.attributes.defaults.merge(attributes))
|
38
|
+
end
|
39
|
+
|
40
|
+
def append_to(type, *objects)
|
41
|
+
update(type => instance_variable_get("@#{type}") + objects)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -15,55 +15,11 @@ module Yaks
|
|
15
15
|
# In the second case a collection has a single "subresource", being its
|
16
16
|
# members.
|
17
17
|
class CollectionResource < Resource
|
18
|
-
include
|
19
|
-
include FP::HashUpdatable.new(:type, :links, :attributes, :members, :collection_rel)
|
20
|
-
include Enumerable
|
18
|
+
include attributes.add(members: [], collection_rel: 'members')
|
21
19
|
|
22
20
|
extend Forwardable
|
23
|
-
|
24
|
-
# @!attribute [r] type
|
25
|
-
# @return [String]
|
26
|
-
# @!attribute [r] links
|
27
|
-
# @return [Array]
|
28
|
-
# @!attribute [r] members
|
29
|
-
# @return [Array]
|
30
|
-
# @!attribute [r] collection_rel
|
31
|
-
# @return [String]
|
32
|
-
attr_reader :type, :links, :members, :collection_rel
|
33
|
-
|
34
21
|
def_delegators :members, :each
|
35
22
|
|
36
|
-
# @param [Hash] options
|
37
|
-
# @return [CollectionResource]
|
38
|
-
def initialize(options)
|
39
|
-
super
|
40
|
-
@members = options.fetch(:members, [])
|
41
|
-
@collection_rel = options.fetch(:collection_rel, 'members')
|
42
|
-
end
|
43
|
-
|
44
|
-
# Make a CollectionResource quack like a resource.
|
45
|
-
#
|
46
|
-
# At the moment this is only for HAL, which always assumes
|
47
|
-
# a singular resource at the top level, this way it can treat
|
48
|
-
# whatever it gets as a single resource with links and subresources,
|
49
|
-
# we just push the collection down one level.
|
50
|
-
#
|
51
|
-
# Once inside subresources the HAL format does check if a resource
|
52
|
-
# is a collection, since there it does make a distinction, and because
|
53
|
-
# in that case it will iterate with each/map rather than calling subresources,
|
54
|
-
# this doesn't cause infinite recursion. Not very pretty, needs looking at.
|
55
|
-
#
|
56
|
-
# :(
|
57
|
-
#
|
58
|
-
# @return [Hash]
|
59
|
-
def subresources
|
60
|
-
if any?
|
61
|
-
{ collection_rel => self }
|
62
|
-
else
|
63
|
-
{}
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
23
|
# @return [Boolean]
|
68
24
|
def collection?
|
69
25
|
true
|
data/lib/yaks/config/dsl.rb
CHANGED
@@ -50,21 +50,30 @@ module Yaks
|
|
50
50
|
config.default_format = format
|
51
51
|
end
|
52
52
|
|
53
|
-
# Configure JSON
|
53
|
+
# Configure serializer for specific output format, e.g. JSON
|
54
54
|
#
|
55
|
-
#
|
55
|
+
# This will override the default registered serializer. Note
|
56
|
+
# that extension gems can register their own serializers, see
|
57
|
+
# Yaks::Serializer.register
|
56
58
|
#
|
57
59
|
# @example
|
58
60
|
#
|
59
61
|
# yaks = Yaks.new do
|
60
|
-
#
|
62
|
+
# serializer :json, &Oj.method(:dump)
|
61
63
|
# end
|
62
64
|
#
|
63
|
-
# @
|
65
|
+
# @type [Symbol] type
|
66
|
+
# Output format
|
67
|
+
# @param [Proc] serializer
|
64
68
|
# Serialization procedure
|
65
69
|
#
|
66
|
-
def
|
67
|
-
config.serializers[
|
70
|
+
def serializer(type, &serializer)
|
71
|
+
config.serializers[type] = serializer
|
72
|
+
end
|
73
|
+
|
74
|
+
# @deprecated
|
75
|
+
def json_serializer(&serializer)
|
76
|
+
serializer(:json, &serializer)
|
68
77
|
end
|
69
78
|
|
70
79
|
%w[before after around skip].map(&:intern).each do |hook_type|
|
data/lib/yaks/config.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Yaks
|
2
|
+
module Configurable
|
3
|
+
def self.included(descendant)
|
4
|
+
descendant.instance_eval do
|
5
|
+
extend ClassMethods
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def config_method(name, options)
|
11
|
+
define_method name do |*args, &block|
|
12
|
+
append_to(
|
13
|
+
options.fetch(:append_to),
|
14
|
+
options.fetch(:create).create(*args, &block)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/yaks/default_policy.rb
CHANGED
@@ -88,13 +88,5 @@ module Yaks
|
|
88
88
|
URITemplate.new(@options[:rel_template]).expand(rel: relname)
|
89
89
|
end
|
90
90
|
|
91
|
-
# @param format_class [Class]
|
92
|
-
# @return [#call] format_class
|
93
|
-
def serializer_for_format(format_class)
|
94
|
-
{
|
95
|
-
json: JSON.method(:pretty_generate),
|
96
|
-
html: :to_html.to_proc
|
97
|
-
}.fetch(format_class.serializer)
|
98
|
-
end
|
99
91
|
end
|
100
92
|
end
|
data/lib/yaks/errors.rb
ADDED
data/lib/yaks/format/hal.rb
CHANGED
@@ -33,8 +33,19 @@ module Yaks
|
|
33
33
|
# resource.
|
34
34
|
#
|
35
35
|
result = resource.attributes
|
36
|
-
|
37
|
-
|
36
|
+
|
37
|
+
if resource.links.any?
|
38
|
+
result = result.merge(_links: serialize_links(resource.links))
|
39
|
+
end
|
40
|
+
|
41
|
+
if resource.collection?
|
42
|
+
result = result.merge(_embedded:
|
43
|
+
serialize_embedded(resource.collection_rel => resource))
|
44
|
+
elsif resource.subresources.any?
|
45
|
+
result = result.merge(_embedded:
|
46
|
+
serialize_embedded(resource.subresources))
|
47
|
+
end
|
48
|
+
|
38
49
|
result
|
39
50
|
end
|
40
51
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Yaks
|
4
|
+
class Format
|
5
|
+
# Extension of Hal loosely based on the example by Mike Kelly given at
|
6
|
+
# https://gist.github.com/mikekelly/893552
|
7
|
+
class Halo < Hal
|
8
|
+
register :halo, :json, 'application/halo+json'
|
9
|
+
|
10
|
+
def serialize_resource(resource)
|
11
|
+
if resource.controls.any?
|
12
|
+
super.merge(_controls: serialize_controls(resource.controls))
|
13
|
+
else
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialize_controls(controls)
|
19
|
+
controls.each_with_object({}) do |control, result|
|
20
|
+
result[control.name] = serialize_control(control)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def serialize_control(control)
|
25
|
+
control.to_h.merge(fields: control.fields.map(&:to_h))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,18 +1,23 @@
|
|
1
1
|
module Yaks
|
2
2
|
class Mapper
|
3
3
|
class Association
|
4
|
-
include
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
include Attributes.new(
|
5
|
+
name: Undefined,
|
6
|
+
item_mapper: Undefined,
|
7
|
+
rel: Undefined,
|
8
|
+
href: Undefined,
|
9
|
+
link_if: Undefined
|
10
|
+
),
|
11
|
+
Util
|
12
|
+
|
13
|
+
def self.create(name, options = {})
|
14
|
+
if options.key?(:mapper)
|
15
|
+
options = options.dup
|
16
|
+
mapper = options.delete(:mapper)
|
17
|
+
options[:item_mapper] = mapper
|
18
|
+
end
|
19
|
+
options[:name] = name
|
20
|
+
new(options)
|
16
21
|
end
|
17
22
|
|
18
23
|
def add_to_resource(resource, parent_mapper, context)
|
@@ -34,7 +39,7 @@ module Yaks
|
|
34
39
|
|
35
40
|
# support for HasOne and HasMany
|
36
41
|
def resolve_association_mapper(policy)
|
37
|
-
return
|
42
|
+
return item_mapper unless item_mapper.equal?(Undefined)
|
38
43
|
policy.derive_mapper_from_association(self)
|
39
44
|
end
|
40
45
|
|
@@ -25,7 +25,7 @@ module Yaks
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def add_link(resource)
|
28
|
-
Link.
|
28
|
+
Link.create(rel, association.href)
|
29
29
|
.add_to_resource(resource, parent_mapper, nil)
|
30
30
|
# Yaks::Mapper::Link doesn't do anything with the context, making it
|
31
31
|
# hard to test that we pass it a context. Passing nil for now, until
|
@@ -3,9 +3,22 @@
|
|
3
3
|
module Yaks
|
4
4
|
class Mapper
|
5
5
|
module ClassMethods
|
6
|
-
include Forwardable
|
7
|
-
|
8
|
-
|
6
|
+
include Forwardable,
|
7
|
+
Util,
|
8
|
+
FP
|
9
|
+
|
10
|
+
def config(value = Undefined)
|
11
|
+
if value.equal? Undefined
|
12
|
+
@config
|
13
|
+
else
|
14
|
+
raise if value.nil?
|
15
|
+
@config = value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def inherited(child)
|
20
|
+
child.config(config)
|
21
|
+
end
|
9
22
|
|
10
23
|
CONFIG_METHODS = [
|
11
24
|
:type,
|
@@ -13,22 +26,17 @@ module Yaks
|
|
13
26
|
:link,
|
14
27
|
:profile,
|
15
28
|
:has_one,
|
16
|
-
:has_many
|
29
|
+
:has_many,
|
30
|
+
:control
|
17
31
|
]
|
18
32
|
|
19
|
-
def config
|
20
|
-
@config ||= Config.new nil, [], [], []
|
21
|
-
@config = yield(@config) if block_given?
|
22
|
-
@config
|
23
|
-
end
|
24
|
-
|
25
|
-
def inherited(child)
|
26
|
-
child.config { @config }
|
27
|
-
end
|
28
|
-
|
29
33
|
CONFIG_METHODS.each do |method_name|
|
30
|
-
define_method method_name do |*args|
|
31
|
-
|
34
|
+
define_method method_name do |*args, &block|
|
35
|
+
if args.empty?
|
36
|
+
config.public_send(method_name, *args, &block)
|
37
|
+
else
|
38
|
+
config(config.public_send(method_name, *args, &block))
|
39
|
+
end
|
32
40
|
end
|
33
41
|
end
|
34
42
|
|
data/lib/yaks/mapper/config.rb
CHANGED
@@ -1,17 +1,10 @@
|
|
1
1
|
module Yaks
|
2
2
|
class Mapper
|
3
3
|
class Config
|
4
|
-
include
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def initialize(type, attributes, links, associations)
|
10
|
-
@type = type
|
11
|
-
@attributes = attributes
|
12
|
-
@links = links
|
13
|
-
@associations = associations
|
14
|
-
end
|
4
|
+
include Attributes.new(
|
5
|
+
type: nil, attributes: [], links: [], associations: [], controls: []
|
6
|
+
),
|
7
|
+
Configurable
|
15
8
|
|
16
9
|
def type(type = Undefined)
|
17
10
|
return @type if type.equal?(Undefined)
|
@@ -20,25 +13,17 @@ module Yaks
|
|
20
13
|
|
21
14
|
def attributes(*attrs)
|
22
15
|
return @attributes if attrs.empty?
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
def link(rel, template, options = {})
|
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))])
|
32
|
-
end
|
33
|
-
|
34
|
-
def has_one(name, options = {})
|
35
|
-
add_association(HasOne, name, options)
|
36
|
-
end
|
37
|
-
|
38
|
-
def has_many(name, options = {})
|
39
|
-
add_association(HasMany, name, options)
|
16
|
+
append_to(:attributes, *attrs.map(&Attribute.method(:new)))
|
40
17
|
end
|
41
18
|
|
19
|
+
config_method :link, create: Link, append_to: :links
|
20
|
+
config_method :has_one, create: HasOne, append_to: :associations
|
21
|
+
config_method :has_many, create: HasMany, append_to: :associations
|
22
|
+
config_method :attribute, create: Attribute, append_to: :attributes
|
23
|
+
config_method :attribute, create: Attribute, append_to: :attributes
|
24
|
+
config_method :control,
|
25
|
+
create: StatefulBuilder.new(Control, Control.anima.attribute_names + [:field]),
|
26
|
+
append_to: :controls
|
42
27
|
end
|
43
28
|
end
|
44
29
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Yaks
|
2
|
+
class Mapper
|
3
|
+
class Control
|
4
|
+
include Attributes.new(
|
5
|
+
name: nil, href: nil, title: nil, method: nil, media_type: nil, fields: []
|
6
|
+
),
|
7
|
+
Configurable
|
8
|
+
|
9
|
+
def self.create(name = nil, options = {})
|
10
|
+
new({name: name}.merge(options))
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_to_resource(resource, _parent_mapper, _context)
|
14
|
+
resource.add_control(
|
15
|
+
::Yaks::Resource::Control.new(to_h.merge(fields: fields.map(&:to_resource_control_field)))
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
class Field
|
20
|
+
include Attributes.new(:name, label: nil, type: "text", value: nil)
|
21
|
+
|
22
|
+
def self.create(*args)
|
23
|
+
attrs = args.last.is_a?(Hash) ? args.pop : {}
|
24
|
+
if name = args.shift
|
25
|
+
attrs = attrs.merge(name: name)
|
26
|
+
end
|
27
|
+
new(attrs)
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_resource_control_field
|
31
|
+
Yaks::Resource::Control::Field.new(to_h)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
config_method :field, create: Field, append_to: :fields
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/yaks/mapper/has_many.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
module Yaks
|
2
2
|
class Mapper
|
3
3
|
class HasMany < Association
|
4
|
-
include Util
|
5
|
-
|
6
|
-
def initialize(options)
|
7
|
-
super
|
8
|
-
@collection_mapper = options.fetch(:collection_mapper, Undefined)
|
9
|
-
end
|
4
|
+
include Util,
|
5
|
+
attributes.add(collection_mapper: Undefined)
|
10
6
|
|
11
7
|
def map_resource(collection, context)
|
12
8
|
return NullResource.new(collection: true) if collection.nil?
|
@@ -16,9 +12,9 @@ module Yaks
|
|
16
12
|
collection_mapper(collection, policy).new(context).call(collection)
|
17
13
|
end
|
18
14
|
|
19
|
-
def collection_mapper(collection, policy)
|
15
|
+
def collection_mapper(collection = nil, policy = nil)
|
20
16
|
return @collection_mapper unless @collection_mapper.equal? Undefined
|
21
|
-
policy.derive_mapper_from_object(collection)
|
17
|
+
policy.derive_mapper_from_object(collection) if policy && collection
|
22
18
|
end
|
23
19
|
|
24
20
|
def singular_name
|
data/lib/yaks/mapper/link.rb
CHANGED
@@ -25,11 +25,15 @@ module Yaks
|
|
25
25
|
# it will receive the mapper instance as argument. Otherwise it is evaluated in the mapper context
|
26
26
|
class Link
|
27
27
|
extend Forwardable
|
28
|
-
include
|
28
|
+
include Attributes.new(:rel, :template, options: {})
|
29
29
|
include Util
|
30
30
|
|
31
31
|
def_delegators :uri_template, :expand_partial
|
32
32
|
|
33
|
+
def self.create(rel, template, options = {})
|
34
|
+
new(rel: rel, template: template, options: options)
|
35
|
+
end
|
36
|
+
|
33
37
|
def add_to_resource(resource, mapper, _context)
|
34
38
|
resource_link = map_to_resource_link(mapper)
|
35
39
|
return resource unless resource_link
|
@@ -70,7 +74,11 @@ module Yaks
|
|
70
74
|
uri = expand_with(mapper.method(:load_attribute))
|
71
75
|
return if uri.nil?
|
72
76
|
|
73
|
-
Resource::Link.new(
|
77
|
+
Resource::Link.new(
|
78
|
+
rel: rel,
|
79
|
+
uri: uri,
|
80
|
+
options: resource_link_options(mapper)
|
81
|
+
)
|
74
82
|
end
|
75
83
|
|
76
84
|
def expand_with(lookup)
|
data/lib/yaks/mapper.rb
CHANGED
@@ -6,7 +6,9 @@ module Yaks
|
|
6
6
|
include Util, FP
|
7
7
|
|
8
8
|
def_delegators 'self.class', :config
|
9
|
-
def_delegators :config, :attributes, :links, :associations
|
9
|
+
def_delegators :config, :attributes, :links, :associations, :controls
|
10
|
+
|
11
|
+
config Config.new
|
10
12
|
|
11
13
|
attr_reader :object, :context
|
12
14
|
|
@@ -41,7 +43,8 @@ module Yaks
|
|
41
43
|
|
42
44
|
[ :map_attributes,
|
43
45
|
:map_links,
|
44
|
-
:map_subresources
|
46
|
+
:map_subresources,
|
47
|
+
:map_controls
|
45
48
|
].inject(Resource.new(type: mapper_name)) do |resource, method|
|
46
49
|
send(method, resource)
|
47
50
|
end
|
@@ -71,5 +74,11 @@ module Yaks
|
|
71
74
|
association.add_to_resource(res, self, context)
|
72
75
|
end
|
73
76
|
end
|
77
|
+
|
78
|
+
def map_controls(resource)
|
79
|
+
controls.inject(resource) do |res, control|
|
80
|
+
control.add_to_resource(res, self, context)
|
81
|
+
end
|
82
|
+
end
|
74
83
|
end
|
75
84
|
end
|
data/lib/yaks/resource/link.rb
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
module Yaks
|
2
2
|
class Resource
|
3
3
|
class Link
|
4
|
-
include
|
5
|
-
|
6
|
-
attr_reader :rel, :uri, :options
|
7
|
-
|
8
|
-
def initialize(rel, uri, options)
|
9
|
-
@rel, @uri, @options = rel, uri, options
|
10
|
-
end
|
4
|
+
include Attributes.new(:rel, :uri, options: {})
|
11
5
|
|
12
6
|
def title
|
13
7
|
options[:title]
|
data/lib/yaks/resource.rb
CHANGED
@@ -1,17 +1,9 @@
|
|
1
1
|
module Yaks
|
2
2
|
class Resource
|
3
|
-
include
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
attr_reader :type, :attributes, :links, :subresources
|
8
|
-
|
9
|
-
def initialize(options = {})
|
10
|
-
@type = options.fetch(:type, nil)
|
11
|
-
@attributes = options.fetch(:attributes, {})
|
12
|
-
@links = options.fetch(:links, [])
|
13
|
-
@subresources = options.fetch(:subresources, {})
|
14
|
-
end
|
3
|
+
include Attributes.new(
|
4
|
+
type: nil, links: [], attributes: {}, subresources: {}, controls: []
|
5
|
+
),
|
6
|
+
Enumerable
|
15
7
|
|
16
8
|
def [](attr)
|
17
9
|
attributes[attr]
|
@@ -41,7 +33,11 @@ module Yaks
|
|
41
33
|
end
|
42
34
|
|
43
35
|
def add_link(link)
|
44
|
-
|
36
|
+
append_to(:links, link)
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_control(control)
|
40
|
+
append_to(:controls, control)
|
45
41
|
end
|
46
42
|
|
47
43
|
def add_subresource(rel, subresource)
|