yaks 0.7.6 → 0.7.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -0
- data/Rakefile +58 -38
- data/lib/yaks.rb +3 -4
- data/lib/yaks/attributes.rb +23 -10
- data/lib/yaks/config.rb +4 -0
- data/lib/yaks/configurable.rb +16 -21
- data/lib/yaks/format.rb +1 -1
- data/lib/yaks/format/collection_json.rb +9 -0
- data/lib/yaks/format/halo.rb +16 -13
- data/lib/yaks/html5_forms.rb +22 -1
- data/lib/yaks/mapper.rb +5 -5
- data/lib/yaks/mapper/attribute.rb +1 -1
- data/lib/yaks/mapper/class_methods.rb +3 -1
- data/lib/yaks/mapper/config.rb +9 -16
- data/lib/yaks/mapper/form.rb +41 -0
- data/lib/yaks/mapper/form/field.rb +62 -0
- data/lib/yaks/null_resource.rb +1 -1
- data/lib/yaks/resource.rb +7 -3
- data/lib/yaks/resource/form.rb +31 -0
- data/lib/yaks/runner.rb +11 -11
- data/lib/yaks/stateful_builder.rb +11 -7
- data/lib/yaks/util.rb +3 -2
- data/lib/yaks/version.rb +1 -1
- data/spec/acceptance/models.rb +1 -1
- data/spec/json/confucius.halo.json +2 -4
- data/spec/json/plant_collection.collection.json +4 -0
- data/spec/unit/yaks/attributes_spec.rb +79 -0
- data/spec/unit/yaks/configurable_spec.rb +32 -2
- data/spec/unit/yaks/format/collection_json_spec.rb +59 -27
- data/spec/unit/yaks/format/halo_spec.rb +3 -0
- data/spec/unit/yaks/mapper/{control → form}/field_spec.rb +3 -3
- data/spec/unit/yaks/mapper/{control_spec.rb → form_spec.rb} +12 -12
- data/spec/unit/yaks/mapper_spec.rb +10 -10
- data/spec/unit/yaks/null_resource_spec.rb +50 -7
- data/spec/unit/yaks/resource_spec.rb +4 -4
- data/spec/unit/yaks/runner_spec.rb +38 -2
- data/spec/unit/yaks/util_spec.rb +42 -0
- metadata +20 -58
- data/lib/yaks/mapper/control.rb +0 -82
- data/lib/yaks/resource/control.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 207388cedc68055dcef4f732bd82ce81180871c8
|
4
|
+
data.tar.gz: 97c121f6e231e8a409d1b2bca7515d75f42d261a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd61481333faaccde1120268996ab50462dcfd2c04f0b08e9340300ad6567a7bf47d59eae2b36471d9661cb9c020304566df8267c3c19f262a77346b7924504e
|
7
|
+
data.tar.gz: 3acfcdfa41752e295833ca61052fbad706e51bae6132eb7f72350bbfd5db1e0d6fa42d1338059d6fa758396d48d417f2c699a8fcfc40888074afde7189c03dfb
|
data/README.md
CHANGED
@@ -23,6 +23,23 @@ requested. These formats are presently supported:
|
|
23
23
|
* HTML
|
24
24
|
* HALO
|
25
25
|
|
26
|
+
## State of Development
|
27
|
+
|
28
|
+
This library came into existence because we at
|
29
|
+
[Ticketsolve](https://www.ticketsolve.com) wanted to build a rich
|
30
|
+
hypermedia API, and were dissatisfied with any of the existing Ruby
|
31
|
+
solutions at the time (November 2013).
|
32
|
+
|
33
|
+
We are still actively expanding our API, and with that Yaks continues
|
34
|
+
to grow and improve. The aim is to create *the reference* for
|
35
|
+
supporting hypermedia formats in Ruby.
|
36
|
+
|
37
|
+
Yaks can be used in production today, as we do, but until 1.0 is
|
38
|
+
released there will regularly be breaking changes, as we figure out
|
39
|
+
the best way to do things. These are all documented clearly in the
|
40
|
+
[changelog](CHANGLOG.md). At this point we recommend locking to an
|
41
|
+
exact version number.
|
42
|
+
|
26
43
|
## Concepts
|
27
44
|
|
28
45
|
Yaks is a processing pipeline, you create and configure the pipeline,
|
data/Rakefile
CHANGED
@@ -2,49 +2,69 @@ load '../rakelib/shared.rake'
|
|
2
2
|
|
3
3
|
gem_tasks(:yaks)
|
4
4
|
|
5
|
-
|
6
5
|
task :mutant_chunked do
|
6
|
+
# No subjects:
|
7
|
+
# Yaks,
|
8
|
+
# Yaks::Error,
|
9
|
+
# Yaks::IllegalStateError,
|
10
|
+
# Yaks::UnsupportedOperationError,
|
11
|
+
# Yaks::PrimitivizeError,
|
12
|
+
# Yaks::Undefined,
|
13
|
+
# Yaks::HTML5Forms,
|
14
|
+
|
15
|
+
# Hangs:
|
16
|
+
# Yaks::Changelog,
|
17
|
+
|
18
|
+
# 100% verified:
|
19
|
+
# Yaks::Util,
|
20
|
+
# Yaks::Util::Deprecated,
|
21
|
+
# Yaks::FP
|
22
|
+
# Yaks::FP::Callable,
|
23
|
+
# Yaks::DefaultPolicy,
|
24
|
+
# Yaks::Mapper::HasOne,
|
25
|
+
# Yaks::Mapper::HasMany,
|
26
|
+
# Yaks::Mapper::Attribute,
|
27
|
+
# Yaks::Mapper::Config,
|
28
|
+
# Yaks::Mapper::ClassMethods,
|
29
|
+
# Yaks::Mapper::AssociationMapper,
|
30
|
+
# Yaks::Format::CollectionJson,
|
31
|
+
# Yaks::Config,
|
32
|
+
# Yaks::Config::DSL,
|
33
|
+
# Yaks::Attributes::InstanceMethods,
|
34
|
+
# Yaks::Configurable,
|
35
|
+
# Yaks::NullResource,
|
36
|
+
|
7
37
|
[
|
8
|
-
Yaks::
|
9
|
-
Yaks::
|
10
|
-
Yaks::
|
11
|
-
Yaks::
|
12
|
-
Yaks::
|
13
|
-
Yaks::
|
14
|
-
Yaks::
|
15
|
-
Yaks::
|
16
|
-
Yaks::
|
17
|
-
Yaks::
|
18
|
-
Yaks::
|
19
|
-
Yaks::
|
20
|
-
Yaks::
|
21
|
-
Yaks::
|
22
|
-
Yaks::
|
23
|
-
Yaks::
|
24
|
-
Yaks::Format::JsonAPI,
|
25
|
-
Yaks::
|
26
|
-
Yaks::
|
27
|
-
Yaks::
|
28
|
-
Yaks::Mapper::
|
29
|
-
Yaks::
|
30
|
-
Yaks::
|
31
|
-
Yaks::
|
32
|
-
Yaks::
|
33
|
-
Yaks::
|
34
|
-
Yaks::Runner,
|
35
|
-
Yaks::Mapper::Link,
|
36
|
-
Yaks::Mapper::HasMany,
|
37
|
-
Yaks::Mapper::ClassMethods,
|
38
|
-
Yaks::Mapper::Association,
|
39
|
-
Yaks::Mapper,
|
40
|
-
Yaks::Format::HTML,
|
41
|
-
Yaks::Mapper::Control,
|
42
|
-
Yaks::Mapper::Control::Field,
|
43
|
-
# Yaks::Resource::Control, #no subjects to mutate
|
44
|
-
Yaks::NullResource,
|
38
|
+
# Yaks::Resource::Form, # no explicit coverage
|
39
|
+
# Yaks::Resource::Form::Field, # no explicit coverage
|
40
|
+
# Yaks::Mapper::Form::Field::Option, # no explicit coverage
|
41
|
+
# Yaks::Format::HTML, # no explicit coverage
|
42
|
+
Yaks::Runner, # 56/509 # 89.55%
|
43
|
+
Yaks::Resource, # 35/206 # 83.01%
|
44
|
+
Yaks::StatefulBuilder, # 25/192 # 86.98%
|
45
|
+
Yaks::Format::Halo, # 24/232 # 89.66%
|
46
|
+
Yaks::Mapper, # 15/482 # 96.89%
|
47
|
+
Yaks::Resource::Link, # 13/43 # 69.77%
|
48
|
+
Yaks::Mapper::Form::Field, # 11/155 # 92.90%
|
49
|
+
Yaks::Mapper::Link, # 10/357 # 97.20%
|
50
|
+
Yaks::CollectionMapper, # 7/217 # 96.77%
|
51
|
+
Yaks::Primitivize, # 3/239 # 98.74%
|
52
|
+
Yaks::Mapper::Form, # 3/179 # 98.32%
|
53
|
+
Yaks::CollectionResource, # 3/9 # 66.67%
|
54
|
+
Yaks::Format::JsonAPI, # 3/435 # 99.31%
|
55
|
+
Yaks::Format, # 2/29 # 93.10%
|
56
|
+
Yaks::Attributes, # 1/239 # 99.57%
|
57
|
+
Yaks::StatefulBuilder::StatefulMethods, # 1/66 # 98.49%
|
58
|
+
Yaks::Mapper::Association, # 1/222 # 99.55%
|
59
|
+
Yaks::Serializer, # 1/74 # 98.65%
|
60
|
+
Yaks::Format::Hal, # 1/328 # 99.70%
|
61
|
+
# Yaks::Format::Transit, # no explicit coverage
|
62
|
+
# Yaks::Format::Transit::WriteHandler, # no explicit coverage
|
63
|
+
# Yaks::Format::Transit::ReadHandler, # no explicit coverage
|
45
64
|
].each do |space|
|
46
65
|
puts space
|
47
66
|
ENV['PATTERN'] = "#{space}"
|
48
67
|
Rake::Task["mutant"].execute
|
68
|
+
break
|
49
69
|
end
|
50
70
|
end
|
data/lib/yaks.rb
CHANGED
@@ -36,10 +36,8 @@ module Yaks
|
|
36
36
|
Yaks::Config.new(&blk)
|
37
37
|
end
|
38
38
|
end
|
39
|
-
|
40
39
|
end
|
41
40
|
|
42
|
-
|
43
41
|
require 'yaks/resource'
|
44
42
|
require 'yaks/null_resource'
|
45
43
|
require 'yaks/resource/link'
|
@@ -52,14 +50,15 @@ require 'yaks/mapper/has_one'
|
|
52
50
|
require 'yaks/mapper/has_many'
|
53
51
|
require 'yaks/mapper/attribute'
|
54
52
|
require 'yaks/mapper/link'
|
55
|
-
require 'yaks/mapper/
|
53
|
+
require 'yaks/mapper/form'
|
54
|
+
require 'yaks/mapper/form/field'
|
56
55
|
require 'yaks/mapper/config'
|
57
56
|
require 'yaks/mapper/class_methods'
|
58
57
|
require 'yaks/mapper'
|
59
58
|
require 'yaks/mapper/association_mapper'
|
60
59
|
require 'yaks/collection_mapper'
|
61
60
|
|
62
|
-
require 'yaks/resource/
|
61
|
+
require 'yaks/resource/form'
|
63
62
|
|
64
63
|
require 'yaks/serializer'
|
65
64
|
|
data/lib/yaks/attributes.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
module Yaks
|
2
2
|
class Attributes < Module
|
3
|
-
attr_reader :defaults, :
|
3
|
+
attr_reader :defaults, :names
|
4
4
|
|
5
5
|
def initialize(*attrs)
|
6
6
|
@defaults = attrs.last.instance_of?(Hash) ? attrs.pop : {}
|
7
|
-
@
|
7
|
+
@names = (attrs + @defaults.keys).uniq
|
8
8
|
end
|
9
9
|
|
10
10
|
def add(*attrs)
|
11
11
|
defaults = attrs.last.instance_of?(Hash) ? attrs.pop : {}
|
12
|
-
self.class.new(*[*(
|
12
|
+
self.class.new(*[*(names+attrs), @defaults.merge(defaults)])
|
13
13
|
end
|
14
14
|
|
15
15
|
def included(descendant)
|
16
16
|
descendant.module_exec(self) do |this|
|
17
17
|
include InstanceMethods,
|
18
|
-
Anima.new(*this.
|
18
|
+
Anima.new(*this.names),
|
19
19
|
Anima::Update
|
20
20
|
|
21
|
-
this.
|
21
|
+
this.names.each do |attr|
|
22
22
|
define_method attr do |value = Undefined|
|
23
23
|
if value.equal? Undefined
|
24
24
|
instance_variable_get("@#{attr}")
|
@@ -45,12 +45,16 @@ module Yaks
|
|
45
45
|
indent = ->(str) { str.lines.map {|l| " #{l}"}.join }
|
46
46
|
format = ->(val) { val.respond_to?(:pp) ? val.pp : val.inspect }
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
defaults = self.class.attributes.defaults
|
49
|
+
values = to_h.reject do |attr, value|
|
50
|
+
value.equal?(defaults[attr])
|
51
|
+
end
|
52
|
+
|
53
|
+
fmt_attrs = values.map do |attr, value|
|
50
54
|
fmt_val = case value
|
51
55
|
when Array
|
52
56
|
if value.inspect.length < 50
|
53
|
-
value.
|
57
|
+
"[#{value.map(&format).join(", ")}]"
|
54
58
|
else
|
55
59
|
"[\n#{indent[value.map(&format).join(",\n")]}\n]"
|
56
60
|
end
|
@@ -58,9 +62,18 @@ module Yaks
|
|
58
62
|
format[value]
|
59
63
|
end
|
60
64
|
"#{attr}: #{fmt_val}"
|
61
|
-
end
|
65
|
+
end
|
66
|
+
|
67
|
+
fmt_attrs_str = fmt_attrs.join(", ")
|
62
68
|
|
63
|
-
|
69
|
+
if fmt_attrs_str.length > 50
|
70
|
+
fmt_attrs_str = fmt_attrs.join(",\n")
|
71
|
+
end
|
72
|
+
|
73
|
+
if fmt_attrs_str =~ /\n/
|
74
|
+
fmt_attrs_str = "\n#{indent[fmt_attrs_str]}\n"
|
75
|
+
end
|
76
|
+
"#{self.class.name}.new(#{fmt_attrs_str})"
|
64
77
|
end
|
65
78
|
end
|
66
79
|
end
|
data/lib/yaks/config.rb
CHANGED
data/lib/yaks/configurable.rb
CHANGED
@@ -1,27 +1,22 @@
|
|
1
1
|
module Yaks
|
2
2
|
module Configurable
|
3
|
-
def
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
def config_method(name, options)
|
4
|
+
define_method name do |*args, &block|
|
5
|
+
defaults = options.fetch(:defaults, {})
|
6
|
+
klass = options.fetch(:create)
|
7
|
+
|
8
|
+
instance = if args.length.equal?(1) && args.first.instance_of?(klass)
|
9
|
+
args.first
|
10
|
+
else
|
11
|
+
if args.last.instance_of?(Hash)
|
12
|
+
args[-1] = defaults.merge(args[-1])
|
13
|
+
else
|
14
|
+
args << defaults
|
15
|
+
end
|
16
|
+
klass.create(*args, &block)
|
17
|
+
end
|
8
18
|
|
9
|
-
|
10
|
-
def config_method(name, options)
|
11
|
-
define_method name do |*args, &block|
|
12
|
-
defaults = options[:defaults]
|
13
|
-
if defaults
|
14
|
-
if args.last.is_a? Hash
|
15
|
-
args[-1] = defaults.merge(args[-1])
|
16
|
-
else
|
17
|
-
args << defaults
|
18
|
-
end
|
19
|
-
end
|
20
|
-
append_to(
|
21
|
-
options.fetch(:append_to),
|
22
|
-
options.fetch(:create).create(*args, &block)
|
23
|
-
)
|
24
|
-
end
|
19
|
+
append_to(options.fetch(:append_to), instance)
|
25
20
|
end
|
26
21
|
end
|
27
22
|
end
|
data/lib/yaks/format.rb
CHANGED
@@ -13,6 +13,7 @@ module Yaks
|
|
13
13
|
items: serialize_items(resource)
|
14
14
|
}
|
15
15
|
result[:href] = resource.self_link.uri if resource.self_link
|
16
|
+
result[:links] = serialize_links(resource) if resource.collection? && resource.links.any?
|
16
17
|
{collection: result}
|
17
18
|
end
|
18
19
|
|
@@ -37,6 +38,14 @@ module Yaks
|
|
37
38
|
result
|
38
39
|
end
|
39
40
|
end
|
41
|
+
|
42
|
+
def serialize_links(resource)
|
43
|
+
result = []
|
44
|
+
resource.links.each do |link|
|
45
|
+
result << {href: link.uri, rel: link.rel}
|
46
|
+
end
|
47
|
+
result
|
48
|
+
end
|
40
49
|
end
|
41
50
|
end
|
42
51
|
end
|
data/lib/yaks/format/halo.rb
CHANGED
@@ -8,28 +8,31 @@ module Yaks
|
|
8
8
|
register :halo, :json, 'application/halo+json'
|
9
9
|
|
10
10
|
def serialize_resource(resource)
|
11
|
-
if resource.
|
12
|
-
super.merge(_controls:
|
11
|
+
if resource.forms.any?
|
12
|
+
super.merge(_controls: serialize_forms(resource.forms))
|
13
13
|
else
|
14
14
|
super
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
|
20
|
-
result[
|
18
|
+
def serialize_forms(forms)
|
19
|
+
forms.each_with_object({}) do |form, result|
|
20
|
+
result[form.name] = serialize_form(form)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
25
|
-
raw =
|
24
|
+
def serialize_form(form)
|
25
|
+
raw = form.to_h
|
26
26
|
raw[:href] = raw.delete(:action)
|
27
|
-
raw[:fields] =
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
raw[:fields] = form.fields.map do |field|
|
28
|
+
field.to_h.each_with_object({}) do |(attr,value), hsh|
|
29
|
+
if attr == :options
|
30
|
+
if !value.empty?
|
31
|
+
hsh[:options] = value.map(&:to_h)
|
32
|
+
end
|
33
|
+
elsif HTML5Forms::FIELD_OPTIONS[attr] != value
|
34
|
+
hsh[attr] = value
|
35
|
+
end
|
33
36
|
end
|
34
37
|
end
|
35
38
|
raw
|
data/lib/yaks/html5_forms.rb
CHANGED
@@ -28,8 +28,29 @@ module Yaks
|
|
28
28
|
:url,
|
29
29
|
:week,
|
30
30
|
|
31
|
-
:select
|
31
|
+
:select,
|
32
|
+
:textarea,
|
33
|
+
:datalist
|
32
34
|
]
|
33
35
|
|
36
|
+
FIELD_OPTIONS = {
|
37
|
+
required: false,
|
38
|
+
rows: nil,
|
39
|
+
type: nil,
|
40
|
+
value: nil,
|
41
|
+
pattern: nil,
|
42
|
+
maxlength: nil,
|
43
|
+
minlength: 0,
|
44
|
+
size: 20,
|
45
|
+
readonly: false,
|
46
|
+
multiple: false,
|
47
|
+
min: nil,
|
48
|
+
max: nil,
|
49
|
+
step: nil,
|
50
|
+
list: nil,
|
51
|
+
placeholder: nil,
|
52
|
+
checked: false
|
53
|
+
}
|
54
|
+
|
34
55
|
end
|
35
56
|
end
|
data/lib/yaks/mapper.rb
CHANGED
@@ -6,7 +6,7 @@ module Yaks
|
|
6
6
|
include Util, FP, FP::Callable
|
7
7
|
|
8
8
|
def_delegators 'self.class', :config
|
9
|
-
def_delegators :config, :attributes, :links, :associations, :
|
9
|
+
def_delegators :config, :attributes, :links, :associations, :forms
|
10
10
|
|
11
11
|
config Config.new
|
12
12
|
|
@@ -44,7 +44,7 @@ module Yaks
|
|
44
44
|
[ :map_attributes,
|
45
45
|
:map_links,
|
46
46
|
:map_subresources,
|
47
|
-
:
|
47
|
+
:map_forms
|
48
48
|
].inject(Resource.new(type: mapper_name)) do |resource, method|
|
49
49
|
send(method, resource)
|
50
50
|
end
|
@@ -100,9 +100,9 @@ module Yaks
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
-
def
|
104
|
-
|
105
|
-
|
103
|
+
def map_forms(resource)
|
104
|
+
forms.inject(resource) do |res, form|
|
105
|
+
form.add_to_resource(res, self, context)
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|