jsonapionify 0.9.0 → 0.9.1
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 +13 -5
- data/.rubocop.yml +1 -0
- data/.ruby-version +1 -1
- data/.travis.yml +8 -0
- data/README.md +85 -3
- data/Rakefile +14 -0
- data/jsonapionify.gemspec +3 -0
- data/lib/jsonapionify/api/action.rb +84 -121
- data/lib/jsonapionify/api/attribute.rb +97 -20
- data/lib/jsonapionify/api/base/class_methods.rb +5 -4
- data/lib/jsonapionify/api/base/delegation.rb +20 -4
- data/lib/jsonapionify/api/base/doc_helper.rb +3 -3
- data/lib/jsonapionify/api/base/reloader.rb +1 -1
- data/lib/jsonapionify/api/base/resource_definitions.rb +28 -15
- data/lib/jsonapionify/api/base.rb +6 -0
- data/lib/jsonapionify/api/context.rb +18 -5
- data/lib/jsonapionify/api/context_delegate.rb +24 -7
- data/lib/jsonapionify/api/errors.rb +2 -0
- data/lib/jsonapionify/api/errors_object.rb +6 -5
- data/lib/jsonapionify/api/relationship/blocks.rb +1 -1
- data/lib/jsonapionify/api/relationship/many.rb +35 -11
- data/lib/jsonapionify/api/relationship/one.rb +17 -7
- data/lib/jsonapionify/api/relationship.rb +20 -6
- data/lib/jsonapionify/api/resource/builders.rb +81 -30
- data/lib/jsonapionify/api/resource/caching.rb +28 -0
- data/lib/jsonapionify/api/resource/caller.rb +61 -0
- data/lib/jsonapionify/api/resource/class_methods.rb +6 -2
- data/lib/jsonapionify/api/resource/defaults/actions.rb +47 -0
- data/lib/jsonapionify/api/resource/defaults/errors.rb +61 -15
- data/lib/jsonapionify/api/resource/defaults/hooks.rb +68 -0
- data/lib/jsonapionify/api/resource/defaults/options.rb +16 -28
- data/lib/jsonapionify/api/resource/defaults/params.rb +3 -0
- data/lib/jsonapionify/api/resource/defaults/request_contexts.rb +80 -32
- data/lib/jsonapionify/api/resource/defaults/response_contexts.rb +13 -6
- data/lib/jsonapionify/api/resource/defaults.rb +1 -1
- data/lib/jsonapionify/api/resource/definitions/actions.rb +81 -55
- data/lib/jsonapionify/api/resource/definitions/attributes.rb +46 -10
- data/lib/jsonapionify/api/resource/definitions/contexts.rb +6 -2
- data/lib/jsonapionify/api/resource/definitions/helpers.rb +1 -1
- data/lib/jsonapionify/api/resource/definitions/pagination.rb +47 -56
- data/lib/jsonapionify/api/resource/definitions/params.rb +11 -15
- data/lib/jsonapionify/api/resource/definitions/relationships.rb +43 -7
- data/lib/jsonapionify/api/resource/definitions/request_headers.rb +6 -3
- data/lib/jsonapionify/api/resource/definitions/response_headers.rb +1 -1
- data/lib/jsonapionify/api/resource/definitions/scopes.rb +5 -5
- data/lib/jsonapionify/api/resource/definitions/sorting.rb +12 -11
- data/lib/jsonapionify/api/resource/definitions.rb +1 -1
- data/lib/jsonapionify/api/resource/error_handling.rb +92 -20
- data/lib/jsonapionify/api/resource/exec.rb +11 -0
- data/lib/jsonapionify/api/resource/includer.rb +89 -1
- data/lib/jsonapionify/api/resource.rb +55 -8
- data/lib/jsonapionify/api/response.rb +43 -14
- data/lib/jsonapionify/api/server/media_type.rb +36 -0
- data/lib/jsonapionify/api/server/request.rb +25 -11
- data/lib/jsonapionify/api/server.rb +8 -4
- data/lib/jsonapionify/api/sort_field.rb +18 -0
- data/lib/jsonapionify/api/sort_field_set.rb +1 -1
- data/lib/jsonapionify/api/test_helper.rb +46 -0
- data/lib/jsonapionify/documentation/template.erb +2 -2
- data/lib/jsonapionify/documentation.rb +10 -0
- data/lib/jsonapionify/structure/collections/base.rb +10 -3
- data/lib/jsonapionify/structure/helpers/object_defaults.rb +5 -10
- data/lib/jsonapionify/structure/maps/relationships.rb +4 -0
- data/lib/jsonapionify/structure/objects/attributes.rb +4 -0
- data/lib/jsonapionify/structure/objects/base.rb +22 -9
- data/lib/jsonapionify/structure/objects/error.rb +2 -0
- data/lib/jsonapionify/structure/objects/jsonapi.rb +1 -0
- data/lib/jsonapionify/structure/objects/link.rb +1 -0
- data/lib/jsonapionify/structure/objects/relationship.rb +2 -0
- data/lib/jsonapionify/structure/objects/resource.rb +2 -0
- data/lib/jsonapionify/structure/objects/resource_identifier.rb +12 -4
- data/lib/jsonapionify/structure/objects/top_level.rb +4 -2
- data/lib/jsonapionify/types/array_type.rb +16 -11
- data/lib/jsonapionify/types/boolean_type.rb +9 -4
- data/lib/jsonapionify/types/date_string_type.rb +7 -10
- data/lib/jsonapionify/types/float_type.rb +13 -0
- data/lib/jsonapionify/types/integer_type.rb +12 -0
- data/lib/jsonapionify/types/object_type.rb +7 -2
- data/lib/jsonapionify/types/string_type.rb +12 -0
- data/lib/jsonapionify/types/time_string_type.rb +8 -10
- data/lib/jsonapionify/types.rb +43 -5
- data/lib/jsonapionify/version.rb +1 -1
- data/lib/jsonapionify.rb +36 -1
- metadata +121 -74
|
@@ -38,6 +38,15 @@ module JSONAPIonify::Api
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
def contains_arel
|
|
42
|
+
case @order
|
|
43
|
+
when :asc
|
|
44
|
+
:gteq
|
|
45
|
+
when :desc
|
|
46
|
+
:lteq
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
41
50
|
def outside_operator
|
|
42
51
|
case @order
|
|
43
52
|
when :asc
|
|
@@ -47,6 +56,15 @@ module JSONAPIonify::Api
|
|
|
47
56
|
end
|
|
48
57
|
end
|
|
49
58
|
|
|
59
|
+
def outside_arel
|
|
60
|
+
case @order
|
|
61
|
+
when :asc
|
|
62
|
+
:gt
|
|
63
|
+
when :desc
|
|
64
|
+
:lt
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
50
68
|
def to_s
|
|
51
69
|
@str
|
|
52
70
|
end
|
|
@@ -6,6 +6,23 @@ module JSONAPIonify
|
|
|
6
6
|
extend ActiveSupport::Concern
|
|
7
7
|
include Rack::Test::Methods
|
|
8
8
|
|
|
9
|
+
included do
|
|
10
|
+
around(:each) do |example|
|
|
11
|
+
begin
|
|
12
|
+
if example.run && last_response && last_response_json
|
|
13
|
+
aggregate_failures do
|
|
14
|
+
"response failures"
|
|
15
|
+
last_response_error_messages&.each do |message|
|
|
16
|
+
expect(message).to be_empty, message
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
rescue Oj::ParseError
|
|
21
|
+
expect(last_response.body).to be_empty, last_response.body
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
9
26
|
module ClassMethods
|
|
10
27
|
def set_api(api)
|
|
11
28
|
define_method(:app) do
|
|
@@ -14,6 +31,35 @@ module JSONAPIonify
|
|
|
14
31
|
end
|
|
15
32
|
end
|
|
16
33
|
|
|
34
|
+
def last_response_error_messages
|
|
35
|
+
last_response_errors&.map do |error|
|
|
36
|
+
{
|
|
37
|
+
id: error['id'],
|
|
38
|
+
code: error['code'],
|
|
39
|
+
status: error['status'],
|
|
40
|
+
title: error['title'],
|
|
41
|
+
detail: error['detail'],
|
|
42
|
+
links: error['links'],
|
|
43
|
+
source: error['source']&.each_with_object([]) { |(k, v), a|
|
|
44
|
+
a << "\n #{k}: #{v}" if v
|
|
45
|
+
}&.join,
|
|
46
|
+
meta: error['meta']&.except('backtrace')&.each_with_object([]) { |(k, v), a|
|
|
47
|
+
a << "\n #{k}: #{v}" if v
|
|
48
|
+
}&.join,
|
|
49
|
+
': ': ':',
|
|
50
|
+
backtrace: ["\n", *(error.dig('meta', 'backtrace') || [])].join("\n")
|
|
51
|
+
}.each_with_object([]) { |(k, v), a|
|
|
52
|
+
a << "#{k}: #{v}" if v&.strip
|
|
53
|
+
}.join("\n")
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def last_response_errors
|
|
58
|
+
last_response_json['errors']
|
|
59
|
+
rescue
|
|
60
|
+
[]
|
|
61
|
+
end
|
|
62
|
+
|
|
17
63
|
def set_headers
|
|
18
64
|
@set_headers ||= Rack::Utils::HeaderHash.new
|
|
19
65
|
end
|
|
@@ -390,8 +390,8 @@
|
|
|
390
390
|
<div class="col-xs-4 attribute-name">
|
|
391
391
|
<strong><%= attribute.name %></strong>
|
|
392
392
|
<i class="attribute-type"><%= attribute.type %></i>
|
|
393
|
-
<% if attribute.required %>
|
|
394
|
-
<p class="optional">required
|
|
393
|
+
<% if attribute.required.present? %>
|
|
394
|
+
<p class="optional">required: <%= attribute.required? %></p>
|
|
395
395
|
<% else %>
|
|
396
396
|
<p class="optional">optional</p>
|
|
397
397
|
<% end %>
|
|
@@ -2,10 +2,12 @@ require 'erb'
|
|
|
2
2
|
require 'redcarpet'
|
|
3
3
|
require 'active_support/core_ext/string/inflections'
|
|
4
4
|
require 'active_support/core_ext/array'
|
|
5
|
+
require 'redcarpet/render_strip'
|
|
5
6
|
|
|
6
7
|
module JSONAPIonify
|
|
7
8
|
class Documentation
|
|
8
9
|
using JSONAPIonify::IndentedString
|
|
10
|
+
STRIPPER = Redcarpet::Markdown.new(Redcarpet::Render::StripDown)
|
|
9
11
|
RENDERER = Redcarpet::Markdown.new(
|
|
10
12
|
Redcarpet::Render::HTML,
|
|
11
13
|
autolink: true,
|
|
@@ -24,6 +26,14 @@ module JSONAPIonify
|
|
|
24
26
|
RENDERER.render(string.deindent)
|
|
25
27
|
end
|
|
26
28
|
|
|
29
|
+
def self.onelinify_markdown(string)
|
|
30
|
+
strip_markdown(string).gsub(/[\r\n\t]/, ' ').strip
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.strip_markdown(string)
|
|
34
|
+
STRIPPER.render(string.deindent)
|
|
35
|
+
end
|
|
36
|
+
|
|
27
37
|
attr_reader :api
|
|
28
38
|
|
|
29
39
|
def initialize(api, template: nil)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
require 'enumerable_observer'
|
|
2
2
|
require 'active_support/core_ext/module/delegation'
|
|
3
|
+
require 'concurrent'
|
|
3
4
|
|
|
4
5
|
module JSONAPIonify::Structure
|
|
5
6
|
module Collections
|
|
6
|
-
class Base < Array
|
|
7
|
+
class Base < Concurrent::Array
|
|
7
8
|
include EnumerableObserver
|
|
8
9
|
include Helpers::InheritsOrigin
|
|
9
10
|
attr_reader :parent
|
|
@@ -72,8 +73,14 @@ module JSONAPIonify::Structure
|
|
|
72
73
|
when type_class
|
|
73
74
|
instance
|
|
74
75
|
else
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
if type_class < instance.class
|
|
77
|
+
type_class.from_hash instance.to_hash
|
|
78
|
+
else
|
|
79
|
+
raise(
|
|
80
|
+
ValidationError,
|
|
81
|
+
"Can't initialize collection `#{self.class.name}` with a type of `#{instance.class.name}`"
|
|
82
|
+
)
|
|
83
|
+
end
|
|
77
84
|
end
|
|
78
85
|
super new_instance
|
|
79
86
|
end
|
|
@@ -59,7 +59,11 @@ module JSONAPIonify::Structure
|
|
|
59
59
|
inherited_hash_attribute :implementations, :collections
|
|
60
60
|
|
|
61
61
|
before_initialize do
|
|
62
|
-
@unset
|
|
62
|
+
@unset = {}
|
|
63
|
+
newly_set = unset.select { |_, v| v.present? }
|
|
64
|
+
newly_set.each do |k, v|
|
|
65
|
+
self[k] = v
|
|
66
|
+
end
|
|
63
67
|
end
|
|
64
68
|
end
|
|
65
69
|
|
|
@@ -80,15 +84,6 @@ module JSONAPIonify::Structure
|
|
|
80
84
|
super k, coerce_value(k, v)
|
|
81
85
|
end
|
|
82
86
|
|
|
83
|
-
def object
|
|
84
|
-
super.tap do
|
|
85
|
-
newly_set = unset.select { |_, v| v.present? }
|
|
86
|
-
newly_set.each do |k, v|
|
|
87
|
-
self[k] = v
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
87
|
private
|
|
93
88
|
|
|
94
89
|
def coerce_value(k, v)
|
|
@@ -5,6 +5,7 @@ require 'active_support/core_ext/hash'
|
|
|
5
5
|
require 'active_support/core_ext/array/conversions'
|
|
6
6
|
require 'active_support/core_ext/hash/keys'
|
|
7
7
|
require 'enumerable_observer'
|
|
8
|
+
require 'concurrent'
|
|
8
9
|
|
|
9
10
|
module JSONAPIonify::Structure
|
|
10
11
|
module Objects
|
|
@@ -24,12 +25,11 @@ module JSONAPIonify::Structure
|
|
|
24
25
|
# Attributes
|
|
25
26
|
attr_reader :object, :parent
|
|
26
27
|
|
|
27
|
-
delegate :fetch, :select, :has_key?, :keys, :values, :each, :present?, :blank?, :empty?, to: :object
|
|
28
28
|
delegate :cache_store, to: JSONAPIonify
|
|
29
|
+
delegate *(Hash.instance_methods - instance_methods), to: :object
|
|
29
30
|
|
|
30
31
|
before_initialize do
|
|
31
|
-
|
|
32
|
-
observe(@object).added do |items|
|
|
32
|
+
observe(self.object).added do |items|
|
|
33
33
|
items.each do |_, value|
|
|
34
34
|
value.instance_variable_set(:@parent, self) unless value.frozen?
|
|
35
35
|
end
|
|
@@ -40,12 +40,21 @@ module JSONAPIonify::Structure
|
|
|
40
40
|
new hash.deep_symbolize_keys
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
def self.define_order(*keys)
|
|
44
|
+
define_singleton_method :ordered_keys do
|
|
45
|
+
keys
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
define_order
|
|
50
|
+
|
|
43
51
|
def self.from_json(json)
|
|
44
52
|
from_hash Oj.load json
|
|
45
53
|
end
|
|
46
54
|
|
|
47
55
|
# Initialize the object
|
|
48
56
|
def initialize(**attributes)
|
|
57
|
+
@object = Concurrent::Hash.new
|
|
49
58
|
run_callbacks :initialize do
|
|
50
59
|
attributes.each do |k, v|
|
|
51
60
|
self[k] = v
|
|
@@ -72,16 +81,16 @@ module JSONAPIonify::Structure
|
|
|
72
81
|
attr_reader :errors, :warnings
|
|
73
82
|
|
|
74
83
|
def compile(validate: true)
|
|
75
|
-
self.validate if validate
|
|
84
|
+
self.validate if validate && !JSONAPIonify.validation_disabled?
|
|
76
85
|
to_hash
|
|
77
86
|
end
|
|
78
87
|
|
|
79
|
-
def as_json
|
|
80
|
-
compile.deep_stringify_keys
|
|
88
|
+
def as_json(**opts)
|
|
89
|
+
compile(**opts).deep_stringify_keys
|
|
81
90
|
end
|
|
82
91
|
|
|
83
|
-
def to_json
|
|
84
|
-
Oj.dump(as_json)
|
|
92
|
+
def to_json(**opts)
|
|
93
|
+
Oj.dump(as_json **opts)
|
|
85
94
|
end
|
|
86
95
|
|
|
87
96
|
def signature
|
|
@@ -89,7 +98,11 @@ module JSONAPIonify::Structure
|
|
|
89
98
|
end
|
|
90
99
|
|
|
91
100
|
def to_hash
|
|
92
|
-
|
|
101
|
+
ordered_object = [
|
|
102
|
+
*object.slice(*self.class.ordered_keys),
|
|
103
|
+
*object.except(*self.class.ordered_keys)
|
|
104
|
+
]
|
|
105
|
+
ordered_object.reduce({}) do |hash, (k, v)|
|
|
93
106
|
hash[k] =
|
|
94
107
|
case v
|
|
95
108
|
when Objects::Base
|
|
@@ -2,6 +2,8 @@ module JSONAPIonify::Structure
|
|
|
2
2
|
module Objects
|
|
3
3
|
# ResourceObjects appear in a JSON API document to represent resources.
|
|
4
4
|
class Resource < ResourceIdentifier
|
|
5
|
+
define_order *%i{type id attributes relationships meta links}
|
|
6
|
+
|
|
5
7
|
# The `id` member is not required when the resource object originates at the
|
|
6
8
|
# client and represents a new resource to be created on the server.
|
|
7
9
|
must_contain! :id, if: ->(obj) { obj.server? } # an id representing the resource
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module JSONAPIonify::Structure
|
|
2
2
|
module Objects
|
|
3
3
|
class ResourceIdentifier < Base
|
|
4
|
+
define_order *%i{type id}
|
|
5
|
+
|
|
4
6
|
# A resource object **MUST** contain at least the following top-level members:
|
|
5
7
|
must_contain! :id, :type # Describes ResourceObjects that share common attributes and relationships.
|
|
6
8
|
|
|
@@ -21,7 +23,11 @@ module JSONAPIonify::Structure
|
|
|
21
23
|
def duplicate_exists?
|
|
22
24
|
return false unless parent.is_a?(Array)
|
|
23
25
|
peers = parent - [self]
|
|
24
|
-
peers.
|
|
26
|
+
!!peers.index(self)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def ==(other)
|
|
30
|
+
same_as? other
|
|
25
31
|
end
|
|
26
32
|
|
|
27
33
|
def duplicate_does_not_exist?
|
|
@@ -30,9 +36,11 @@ module JSONAPIonify::Structure
|
|
|
30
36
|
|
|
31
37
|
def same_as?(other)
|
|
32
38
|
return false unless other.is_a? ResourceIdentifier
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
other_type, other_id = other.values_at :type, :id
|
|
40
|
+
local_type, local_id = values_at :type, :id
|
|
41
|
+
other_type == local_type &&
|
|
42
|
+
!(other_id || local_id).nil? &&
|
|
43
|
+
other_id == local_id
|
|
36
44
|
end
|
|
37
45
|
|
|
38
46
|
end
|
|
@@ -8,6 +8,8 @@ module JSONAPIonify::Structure
|
|
|
8
8
|
class TopLevel < Base
|
|
9
9
|
attr_reader :origin
|
|
10
10
|
|
|
11
|
+
define_order *%i{jsonapi data included errors meta links}
|
|
12
|
+
|
|
11
13
|
default(:jsonapi) { Jsonapi.new version: '1.0' }
|
|
12
14
|
|
|
13
15
|
# A document **MUST** contain at least one of:
|
|
@@ -75,8 +77,8 @@ module JSONAPIonify::Structure
|
|
|
75
77
|
Collections::ResourceIdentifiers
|
|
76
78
|
]
|
|
77
79
|
|
|
78
|
-
def compile(
|
|
79
|
-
compiled = super(
|
|
80
|
+
def compile(**opts)
|
|
81
|
+
compiled = super(**opts)
|
|
80
82
|
compiled_errors = compiled['errors'] || []
|
|
81
83
|
all_errors = compiled_errors | errors.as_collection.compile
|
|
82
84
|
if all_errors.present?
|
|
@@ -7,24 +7,29 @@ module JSONAPIonify::Types
|
|
|
7
7
|
end
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
options[:of].
|
|
10
|
+
def sample(field_name)
|
|
11
|
+
field_name = field_name.to_s.singularize.to_sym
|
|
12
|
+
3.times.map do
|
|
13
|
+
(options[:of] || StringType.new).sample(field_name)
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
loader do |value|
|
|
18
|
+
raise LoadError, 'invalid type' unless value.is_a?(Array)
|
|
19
|
+
return super(value) unless options[:of]
|
|
19
20
|
value.map do |item|
|
|
20
|
-
options[:of].
|
|
21
|
+
options[:of].load(item)
|
|
21
22
|
end
|
|
22
23
|
end
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
dumper do |value|
|
|
26
|
+
raise DumpError, 'cannot convert value to array' unless value.respond_to?(:to_a)
|
|
27
|
+
value.to_a.tap do |array|
|
|
28
|
+
raise DumpError, 'output value was not an array' unless array.is_a? Array
|
|
29
|
+
end
|
|
30
|
+
return super(value) unless options[:of]
|
|
31
|
+
value.map do |item|
|
|
32
|
+
options[:of].dump(item)
|
|
28
33
|
end
|
|
29
34
|
end
|
|
30
35
|
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
module JSONAPIonify::Types
|
|
2
2
|
class BooleanType < BaseType
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
value
|
|
4
|
+
loader do |value|
|
|
5
|
+
case value
|
|
6
|
+
when true, false
|
|
7
|
+
value
|
|
8
|
+
else
|
|
9
|
+
raise LoadError, "#{value} is not a valid JSON #{name}."
|
|
10
|
+
end
|
|
6
11
|
end
|
|
7
12
|
|
|
8
|
-
|
|
13
|
+
dumper do |value|
|
|
9
14
|
case value
|
|
10
15
|
when true, false
|
|
11
16
|
value
|
|
12
17
|
else
|
|
13
|
-
raise
|
|
18
|
+
raise DumpError, "#{value} is not a valid JSON #{name}."
|
|
14
19
|
end
|
|
15
20
|
end
|
|
16
21
|
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
require 'faker'
|
|
2
2
|
|
|
3
3
|
module JSONAPIonify::Types
|
|
4
|
-
class DateStringType <
|
|
5
|
-
|
|
6
|
-
Date.parse value
|
|
4
|
+
class DateStringType < StringType
|
|
5
|
+
loader do |value|
|
|
6
|
+
Date.parse super(value)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
JSON.load JSON.dump(value.to_date)
|
|
13
|
-
else
|
|
14
|
-
raise TypeError, "#{value} is not a valid JSON #{name}."
|
|
15
|
-
end
|
|
9
|
+
dumper do |value|
|
|
10
|
+
raise DumpError, 'cannot convert value to date' unless value.respond_to?(:to_date)
|
|
11
|
+
JSON.load JSON.dump(value.to_date)
|
|
16
12
|
end
|
|
17
13
|
|
|
18
14
|
def sample(field_name)
|
|
@@ -26,3 +22,4 @@ module JSONAPIonify::Types
|
|
|
26
22
|
|
|
27
23
|
end
|
|
28
24
|
end
|
|
25
|
+
|
|
@@ -4,5 +4,18 @@ module JSONAPIonify::Types
|
|
|
4
4
|
def sample(*)
|
|
5
5
|
rand(0.0..201.42).round(2)
|
|
6
6
|
end
|
|
7
|
+
|
|
8
|
+
loader do |value|
|
|
9
|
+
raise LoadError, 'input value was not a float' unless value.is_a?(Float)
|
|
10
|
+
value
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
dumper do |value|
|
|
14
|
+
raise DumpError, 'cannot convert value to float' unless value.respond_to?(:to_f)
|
|
15
|
+
value.to_f.tap do |float|
|
|
16
|
+
raise DumpError, 'output value was not a float' unless float.is_a? Float
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
7
20
|
end
|
|
8
21
|
end
|
|
@@ -5,5 +5,17 @@ module JSONAPIonify::Types
|
|
|
5
5
|
rand(1..123)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
loader do |value|
|
|
9
|
+
raise LoadError, 'input value was not an integer' unless value.is_a?(Fixnum)
|
|
10
|
+
value
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
dumper do |value|
|
|
14
|
+
raise DumpError, 'cannot convert value to integer' unless value.respond_to?(:to_i)
|
|
15
|
+
value.to_i.tap do |int|
|
|
16
|
+
raise DumpError, 'output value was not a integer' unless int.is_a? Fixnum
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
8
20
|
end
|
|
9
21
|
end
|
|
@@ -3,11 +3,16 @@ require 'active_support/core_ext/hash/keys'
|
|
|
3
3
|
module JSONAPIonify::Types
|
|
4
4
|
class ObjectType < BaseType
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
loader do |value|
|
|
7
|
+
raise LoadError, 'invalid type' unless value.is_a?(Hash)
|
|
7
8
|
super(value).deep_symbolize_keys
|
|
8
9
|
end
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
dumper do |value|
|
|
12
|
+
raise DumpError, 'cannot convert value to hash' unless value.respond_to?(:to_h)
|
|
13
|
+
value = value.to_h.tap do |hash|
|
|
14
|
+
raise DumpError, 'output value was not a hash' unless hash.is_a? Hash
|
|
15
|
+
end
|
|
11
16
|
super(value.deep_stringify_keys)
|
|
12
17
|
end
|
|
13
18
|
|
|
@@ -59,6 +59,18 @@ module JSONAPIonify::Types
|
|
|
59
59
|
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
loader do |value|
|
|
63
|
+
raise LoadError, 'input value was not a string' unless value.is_a?(String)
|
|
64
|
+
value
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
dumper do |value|
|
|
68
|
+
raise DumpError, 'cannot convert value to string' unless value.respond_to?(:to_s)
|
|
69
|
+
value.to_s.tap do |string|
|
|
70
|
+
raise DumpError, 'output value was not a string' unless string.is_a? String
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
62
74
|
def sample(field_name)
|
|
63
75
|
StringSampler.new(field_name).value
|
|
64
76
|
end
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
require 'faker'
|
|
2
2
|
|
|
3
3
|
module JSONAPIonify::Types
|
|
4
|
-
class TimeStringType <
|
|
5
|
-
|
|
6
|
-
Time.parse value
|
|
4
|
+
class TimeStringType < StringType
|
|
5
|
+
loader do |value|
|
|
6
|
+
Time.parse super(value)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
JSON.load JSON.dump(value.to_time)
|
|
13
|
-
else
|
|
14
|
-
raise TypeError, "#{value} is not a valid JSON #{name}."
|
|
15
|
-
end
|
|
9
|
+
dumper do |value|
|
|
10
|
+
raise DumpError, 'cannot convert value to time' unless value.respond_to?(:to_time)
|
|
11
|
+
JSON.load JSON.dump(value.to_time.utc)
|
|
16
12
|
end
|
|
17
13
|
|
|
18
14
|
def sample(field_name)
|
|
@@ -21,6 +17,8 @@ module JSONAPIonify::Types
|
|
|
21
17
|
Faker::Time.backward
|
|
22
18
|
elsif field_name.include?('end')
|
|
23
19
|
Faker::Time.forward
|
|
20
|
+
else
|
|
21
|
+
Faker::Time.backward
|
|
24
22
|
end
|
|
25
23
|
end
|
|
26
24
|
|