yaks 0.6.0.alpha.1 → 0.6.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 +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)
|