json_api_client 1.23.0 → 1.24.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/LICENSE +20 -20
- data/README.md +723 -705
- data/Rakefile +32 -32
- data/lib/json_api_client/associations/base_association.rb +33 -33
- data/lib/json_api_client/associations/belongs_to.rb +31 -31
- data/lib/json_api_client/associations/has_many.rb +7 -7
- data/lib/json_api_client/associations/has_one.rb +16 -16
- data/lib/json_api_client/associations.rb +7 -7
- data/lib/json_api_client/connection.rb +41 -41
- data/lib/json_api_client/error_collector.rb +91 -91
- data/lib/json_api_client/errors.rb +125 -125
- data/lib/json_api_client/formatter.rb +145 -145
- data/lib/json_api_client/helpers/associatable.rb +88 -88
- data/lib/json_api_client/helpers/callbacks.rb +27 -27
- data/lib/json_api_client/helpers/dirty.rb +75 -75
- data/lib/json_api_client/helpers/dynamic_attributes.rb +78 -78
- data/lib/json_api_client/helpers/uri.rb +9 -9
- data/lib/json_api_client/helpers.rb +9 -9
- data/lib/json_api_client/implementation.rb +11 -11
- data/lib/json_api_client/included_data.rb +58 -58
- data/lib/json_api_client/linking/links.rb +21 -21
- data/lib/json_api_client/linking/top_level_links.rb +39 -39
- data/lib/json_api_client/linking.rb +5 -5
- data/lib/json_api_client/meta_data.rb +19 -19
- data/lib/json_api_client/middleware/json_request.rb +26 -26
- data/lib/json_api_client/middleware/status.rb +67 -67
- data/lib/json_api_client/middleware.rb +6 -6
- data/lib/json_api_client/paginating/nested_param_paginator.rb +140 -140
- data/lib/json_api_client/paginating/paginator.rb +89 -89
- data/lib/json_api_client/paginating.rb +6 -6
- data/lib/json_api_client/parsers/parser.rb +102 -102
- data/lib/json_api_client/parsers.rb +4 -4
- data/lib/json_api_client/query/builder.rb +239 -239
- data/lib/json_api_client/query/requestor.rb +73 -73
- data/lib/json_api_client/query.rb +5 -5
- data/lib/json_api_client/relationships/relations.rb +55 -55
- data/lib/json_api_client/relationships/top_level_relations.rb +30 -30
- data/lib/json_api_client/relationships.rb +5 -5
- data/lib/json_api_client/request_params.rb +57 -57
- data/lib/json_api_client/resource.rb +671 -671
- data/lib/json_api_client/result_set.rb +25 -25
- data/lib/json_api_client/schema.rb +154 -154
- data/lib/json_api_client/utils.rb +53 -53
- data/lib/json_api_client/version.rb +3 -3
- data/lib/json_api_client.rb +30 -30
- metadata +55 -30
|
@@ -1,140 +1,140 @@
|
|
|
1
|
-
module JsonApiClient
|
|
2
|
-
module Paginating
|
|
3
|
-
# An alternate, more consistent Paginator that always wraps
|
|
4
|
-
# pagination query string params in a top-level wrapper_name,
|
|
5
|
-
# e.g. page[offset]=2, page[limit]=10.
|
|
6
|
-
class NestedParamPaginator
|
|
7
|
-
DEFAULT_WRAPPER_NAME = "page".freeze
|
|
8
|
-
DEFAULT_PAGE_PARAM = "page".freeze
|
|
9
|
-
DEFAULT_PER_PAGE_PARAM = "per_page".freeze
|
|
10
|
-
|
|
11
|
-
# Define class accessors as methods to enforce standard way
|
|
12
|
-
# of defining pagination related query string params.
|
|
13
|
-
class << self
|
|
14
|
-
|
|
15
|
-
def wrapper_name
|
|
16
|
-
@_wrapper_name ||= DEFAULT_WRAPPER_NAME
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def wrapper_name=(param = DEFAULT_WRAPPER_NAME)
|
|
20
|
-
raise ArgumentError, "don't wrap wrapper_name" unless valid_param?(param)
|
|
21
|
-
|
|
22
|
-
@_wrapper_name = param.to_s
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def page_param
|
|
26
|
-
@_page_param ||= DEFAULT_PAGE_PARAM
|
|
27
|
-
"#{wrapper_name}[#{@_page_param}]"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def page_param=(param = DEFAULT_PAGE_PARAM)
|
|
31
|
-
raise ArgumentError, "don't wrap page_param" unless valid_param?(param)
|
|
32
|
-
|
|
33
|
-
@_page_param = param.to_s
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def per_page_param
|
|
37
|
-
@_per_page_param ||= DEFAULT_PER_PAGE_PARAM
|
|
38
|
-
"#{wrapper_name}[#{@_per_page_param}]"
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def per_page_param=(param = DEFAULT_PER_PAGE_PARAM)
|
|
42
|
-
raise ArgumentError, "don't wrap per_page_param" unless valid_param?(param)
|
|
43
|
-
|
|
44
|
-
@_per_page_param = param
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
private
|
|
48
|
-
|
|
49
|
-
def valid_param?(param)
|
|
50
|
-
!(param.nil? || param.to_s.include?("[") || param.to_s.include?("]"))
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
attr_reader :params, :result_set, :links
|
|
56
|
-
|
|
57
|
-
def initialize(result_set, data)
|
|
58
|
-
@params = params_for_uri(result_set.uri)
|
|
59
|
-
@result_set = result_set
|
|
60
|
-
@links = data["links"]
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def next
|
|
64
|
-
result_set.links.fetch_link("next")
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def prev
|
|
68
|
-
result_set.links.fetch_link("prev")
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def first
|
|
72
|
-
result_set.links.fetch_link("first")
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def last
|
|
76
|
-
result_set.links.fetch_link("last")
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def total_pages
|
|
80
|
-
if links["last"]
|
|
81
|
-
uri = result_set.links.link_url_for("last")
|
|
82
|
-
last_params = params_for_uri(uri)
|
|
83
|
-
last_params.fetch(page_param, &method(:current_page)).to_i
|
|
84
|
-
else
|
|
85
|
-
current_page
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# this is an estimate, not necessarily an exact count
|
|
90
|
-
def total_entries
|
|
91
|
-
per_page * total_pages
|
|
92
|
-
end
|
|
93
|
-
def total_count; total_entries; end
|
|
94
|
-
|
|
95
|
-
def offset
|
|
96
|
-
per_page * (current_page - 1)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def per_page
|
|
100
|
-
params.fetch(per_page_param) do
|
|
101
|
-
result_set.length
|
|
102
|
-
end.to_i
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def current_page
|
|
106
|
-
params.fetch(page_param, 1).to_i
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def out_of_bounds?
|
|
110
|
-
current_page > total_pages
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def previous_page
|
|
114
|
-
current_page > 1 ? (current_page - 1) : nil
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def next_page
|
|
118
|
-
current_page < total_pages ? (current_page + 1) : nil
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def page_param
|
|
122
|
-
self.class.page_param
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def per_page_param
|
|
126
|
-
self.class.per_page_param
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
alias limit_value per_page
|
|
130
|
-
|
|
131
|
-
protected
|
|
132
|
-
|
|
133
|
-
def params_for_uri(uri)
|
|
134
|
-
return {} unless uri
|
|
135
|
-
uri = Addressable::URI.parse(uri)
|
|
136
|
-
( uri.query_values || {} ).with_indifferent_access
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
end
|
|
1
|
+
module JsonApiClient
|
|
2
|
+
module Paginating
|
|
3
|
+
# An alternate, more consistent Paginator that always wraps
|
|
4
|
+
# pagination query string params in a top-level wrapper_name,
|
|
5
|
+
# e.g. page[offset]=2, page[limit]=10.
|
|
6
|
+
class NestedParamPaginator
|
|
7
|
+
DEFAULT_WRAPPER_NAME = "page".freeze
|
|
8
|
+
DEFAULT_PAGE_PARAM = "page".freeze
|
|
9
|
+
DEFAULT_PER_PAGE_PARAM = "per_page".freeze
|
|
10
|
+
|
|
11
|
+
# Define class accessors as methods to enforce standard way
|
|
12
|
+
# of defining pagination related query string params.
|
|
13
|
+
class << self
|
|
14
|
+
|
|
15
|
+
def wrapper_name
|
|
16
|
+
@_wrapper_name ||= DEFAULT_WRAPPER_NAME
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def wrapper_name=(param = DEFAULT_WRAPPER_NAME)
|
|
20
|
+
raise ArgumentError, "don't wrap wrapper_name" unless valid_param?(param)
|
|
21
|
+
|
|
22
|
+
@_wrapper_name = param.to_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def page_param
|
|
26
|
+
@_page_param ||= DEFAULT_PAGE_PARAM
|
|
27
|
+
"#{wrapper_name}[#{@_page_param}]"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def page_param=(param = DEFAULT_PAGE_PARAM)
|
|
31
|
+
raise ArgumentError, "don't wrap page_param" unless valid_param?(param)
|
|
32
|
+
|
|
33
|
+
@_page_param = param.to_s
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def per_page_param
|
|
37
|
+
@_per_page_param ||= DEFAULT_PER_PAGE_PARAM
|
|
38
|
+
"#{wrapper_name}[#{@_per_page_param}]"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def per_page_param=(param = DEFAULT_PER_PAGE_PARAM)
|
|
42
|
+
raise ArgumentError, "don't wrap per_page_param" unless valid_param?(param)
|
|
43
|
+
|
|
44
|
+
@_per_page_param = param
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def valid_param?(param)
|
|
50
|
+
!(param.nil? || param.to_s.include?("[") || param.to_s.include?("]"))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
attr_reader :params, :result_set, :links
|
|
56
|
+
|
|
57
|
+
def initialize(result_set, data)
|
|
58
|
+
@params = params_for_uri(result_set.uri)
|
|
59
|
+
@result_set = result_set
|
|
60
|
+
@links = data["links"]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def next
|
|
64
|
+
result_set.links.fetch_link("next")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def prev
|
|
68
|
+
result_set.links.fetch_link("prev")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def first
|
|
72
|
+
result_set.links.fetch_link("first")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def last
|
|
76
|
+
result_set.links.fetch_link("last")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def total_pages
|
|
80
|
+
if links["last"]
|
|
81
|
+
uri = result_set.links.link_url_for("last")
|
|
82
|
+
last_params = params_for_uri(uri)
|
|
83
|
+
last_params.fetch(page_param, &method(:current_page)).to_i
|
|
84
|
+
else
|
|
85
|
+
current_page
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# this is an estimate, not necessarily an exact count
|
|
90
|
+
def total_entries
|
|
91
|
+
per_page * total_pages
|
|
92
|
+
end
|
|
93
|
+
def total_count; total_entries; end
|
|
94
|
+
|
|
95
|
+
def offset
|
|
96
|
+
per_page * (current_page - 1)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def per_page
|
|
100
|
+
params.fetch(per_page_param) do
|
|
101
|
+
result_set.length
|
|
102
|
+
end.to_i
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def current_page
|
|
106
|
+
params.fetch(page_param, 1).to_i
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def out_of_bounds?
|
|
110
|
+
current_page > total_pages
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def previous_page
|
|
114
|
+
current_page > 1 ? (current_page - 1) : nil
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def next_page
|
|
118
|
+
current_page < total_pages ? (current_page + 1) : nil
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def page_param
|
|
122
|
+
self.class.page_param
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def per_page_param
|
|
126
|
+
self.class.per_page_param
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
alias limit_value per_page
|
|
130
|
+
|
|
131
|
+
protected
|
|
132
|
+
|
|
133
|
+
def params_for_uri(uri)
|
|
134
|
+
return {} unless uri
|
|
135
|
+
uri = Addressable::URI.parse(uri)
|
|
136
|
+
( uri.query_values || {} ).with_indifferent_access
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -1,89 +1,89 @@
|
|
|
1
|
-
module JsonApiClient
|
|
2
|
-
module Paginating
|
|
3
|
-
class Paginator
|
|
4
|
-
class_attribute :page_param,
|
|
5
|
-
:per_page_param
|
|
6
|
-
|
|
7
|
-
self.page_param = "page"
|
|
8
|
-
self.per_page_param = "per_page"
|
|
9
|
-
|
|
10
|
-
attr_reader :params, :result_set, :links
|
|
11
|
-
|
|
12
|
-
def initialize(result_set, data)
|
|
13
|
-
@params = params_for_uri(result_set.uri)
|
|
14
|
-
@result_set = result_set
|
|
15
|
-
@links = data["links"]
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def next
|
|
19
|
-
result_set.links.fetch_link("next")
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def prev
|
|
23
|
-
result_set.links.fetch_link("prev")
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def first
|
|
27
|
-
result_set.links.fetch_link("first")
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def last
|
|
31
|
-
result_set.links.fetch_link("last")
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def total_pages
|
|
35
|
-
if links["last"]
|
|
36
|
-
uri = result_set.links.link_url_for("last")
|
|
37
|
-
last_params = params_for_uri(uri)
|
|
38
|
-
last_params.fetch(page_param) do
|
|
39
|
-
current_page
|
|
40
|
-
end.to_i
|
|
41
|
-
else
|
|
42
|
-
current_page
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# this number may be off
|
|
47
|
-
def total_entries
|
|
48
|
-
per_page * total_pages
|
|
49
|
-
end
|
|
50
|
-
def total_count; total_entries; end
|
|
51
|
-
|
|
52
|
-
def offset
|
|
53
|
-
per_page * (current_page - 1)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def per_page
|
|
57
|
-
params.fetch(per_page_param) do
|
|
58
|
-
result_set.length
|
|
59
|
-
end.to_i
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def current_page
|
|
63
|
-
params.fetch(page_param, 1).to_i
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def out_of_bounds?
|
|
67
|
-
current_page > total_pages
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def previous_page
|
|
71
|
-
current_page > 1 ? (current_page - 1) : nil
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def next_page
|
|
75
|
-
current_page < total_pages ? (current_page + 1) : nil
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
alias limit_value per_page
|
|
79
|
-
|
|
80
|
-
protected
|
|
81
|
-
|
|
82
|
-
def params_for_uri(uri)
|
|
83
|
-
return {} unless uri
|
|
84
|
-
uri = Addressable::URI.parse(uri)
|
|
85
|
-
( uri.query_values || {} ).with_indifferent_access
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end
|
|
1
|
+
module JsonApiClient
|
|
2
|
+
module Paginating
|
|
3
|
+
class Paginator
|
|
4
|
+
class_attribute :page_param,
|
|
5
|
+
:per_page_param
|
|
6
|
+
|
|
7
|
+
self.page_param = "page"
|
|
8
|
+
self.per_page_param = "per_page"
|
|
9
|
+
|
|
10
|
+
attr_reader :params, :result_set, :links
|
|
11
|
+
|
|
12
|
+
def initialize(result_set, data)
|
|
13
|
+
@params = params_for_uri(result_set.uri)
|
|
14
|
+
@result_set = result_set
|
|
15
|
+
@links = data["links"]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def next
|
|
19
|
+
result_set.links.fetch_link("next")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def prev
|
|
23
|
+
result_set.links.fetch_link("prev")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def first
|
|
27
|
+
result_set.links.fetch_link("first")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def last
|
|
31
|
+
result_set.links.fetch_link("last")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def total_pages
|
|
35
|
+
if links["last"]
|
|
36
|
+
uri = result_set.links.link_url_for("last")
|
|
37
|
+
last_params = params_for_uri(uri)
|
|
38
|
+
last_params.fetch(page_param) do
|
|
39
|
+
current_page
|
|
40
|
+
end.to_i
|
|
41
|
+
else
|
|
42
|
+
current_page
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# this number may be off
|
|
47
|
+
def total_entries
|
|
48
|
+
per_page * total_pages
|
|
49
|
+
end
|
|
50
|
+
def total_count; total_entries; end
|
|
51
|
+
|
|
52
|
+
def offset
|
|
53
|
+
per_page * (current_page - 1)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def per_page
|
|
57
|
+
params.fetch(per_page_param) do
|
|
58
|
+
result_set.length
|
|
59
|
+
end.to_i
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def current_page
|
|
63
|
+
params.fetch(page_param, 1).to_i
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def out_of_bounds?
|
|
67
|
+
current_page > total_pages
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def previous_page
|
|
71
|
+
current_page > 1 ? (current_page - 1) : nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def next_page
|
|
75
|
+
current_page < total_pages ? (current_page + 1) : nil
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
alias limit_value per_page
|
|
79
|
+
|
|
80
|
+
protected
|
|
81
|
+
|
|
82
|
+
def params_for_uri(uri)
|
|
83
|
+
return {} unless uri
|
|
84
|
+
uri = Addressable::URI.parse(uri)
|
|
85
|
+
( uri.query_values || {} ).with_indifferent_access
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
module JsonApiClient
|
|
2
|
-
module Paginating
|
|
3
|
-
autoload :Paginator, 'json_api_client/paginating/paginator'
|
|
4
|
-
autoload :NestedParamPaginator, 'json_api_client/paginating/nested_param_paginator'
|
|
5
|
-
end
|
|
6
|
-
end
|
|
1
|
+
module JsonApiClient
|
|
2
|
+
module Paginating
|
|
3
|
+
autoload :Paginator, 'json_api_client/paginating/paginator'
|
|
4
|
+
autoload :NestedParamPaginator, 'json_api_client/paginating/nested_param_paginator'
|
|
5
|
+
end
|
|
6
|
+
end
|
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
module JsonApiClient
|
|
2
|
-
module Parsers
|
|
3
|
-
class Parser
|
|
4
|
-
class << self
|
|
5
|
-
def parse(klass, response)
|
|
6
|
-
data = response.body.present? ? response.body : {}
|
|
7
|
-
|
|
8
|
-
ResultSet.new.tap do |result_set|
|
|
9
|
-
result_set.record_class = klass
|
|
10
|
-
result_set.uri = response.env[:url]
|
|
11
|
-
handle_json_api(result_set, data)
|
|
12
|
-
handle_data(result_set, data)
|
|
13
|
-
handle_errors(result_set, data)
|
|
14
|
-
handle_meta(result_set, data)
|
|
15
|
-
handle_links(result_set, data)
|
|
16
|
-
handle_relationships(result_set, data)
|
|
17
|
-
handle_pagination(result_set, data)
|
|
18
|
-
handle_included(result_set, data)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
#
|
|
23
|
-
# Given a resource hash, returns a Resource.new friendly hash
|
|
24
|
-
# which flattens the attributes in w/ id and type.
|
|
25
|
-
#
|
|
26
|
-
# Example:
|
|
27
|
-
#
|
|
28
|
-
# Given:
|
|
29
|
-
# {
|
|
30
|
-
# id: 1.
|
|
31
|
-
# type: 'person',
|
|
32
|
-
# attributes: {
|
|
33
|
-
# first_name: 'Jeff',
|
|
34
|
-
# last_name: 'Ching'
|
|
35
|
-
# },
|
|
36
|
-
# links: {...},
|
|
37
|
-
# relationships: {...}
|
|
38
|
-
# }
|
|
39
|
-
#
|
|
40
|
-
# Returns:
|
|
41
|
-
# {
|
|
42
|
-
# id: 1,
|
|
43
|
-
# type: 'person',
|
|
44
|
-
# first_name: 'Jeff',
|
|
45
|
-
# last_name: 'Ching'
|
|
46
|
-
# links: {...},
|
|
47
|
-
# relationships: {...}
|
|
48
|
-
# }
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
def parameters_from_resource(params)
|
|
52
|
-
attrs = params.slice('id', 'links', 'meta', 'type', 'relationships')
|
|
53
|
-
attrs.merge(params.fetch('attributes', {}))
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
private
|
|
57
|
-
|
|
58
|
-
def handle_json_api(result_set, data)
|
|
59
|
-
result_set.implementation = Implementation.new(data.fetch("jsonapi", {}))
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def handle_data(result_set, data)
|
|
63
|
-
# all data lives under the "data" attribute
|
|
64
|
-
results = data.fetch("data", [])
|
|
65
|
-
|
|
66
|
-
# we will treat everything as an Array
|
|
67
|
-
results = [results] unless results.is_a?(Array)
|
|
68
|
-
resources = results.compact.map do |res|
|
|
69
|
-
resource = result_set.record_class.load(parameters_from_resource(res))
|
|
70
|
-
resource.last_result_set = result_set
|
|
71
|
-
resource
|
|
72
|
-
end
|
|
73
|
-
result_set.concat(resources)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def handle_errors(result_set, data)
|
|
77
|
-
result_set.errors = ErrorCollector.new(data.fetch("errors", []))
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def handle_meta(result_set, data)
|
|
81
|
-
result_set.meta = MetaData.new(data.fetch("meta", {}), result_set.record_class)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def handle_links(result_set, data)
|
|
85
|
-
result_set.links = Linking::TopLevelLinks.new(result_set.record_class, data.fetch("links", {}))
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def handle_relationships(result_set, data)
|
|
89
|
-
result_set.relationships = Relationships::TopLevelRelations.new(result_set.record_class, data.fetch("relationships", {}))
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def handle_pagination(result_set, data)
|
|
93
|
-
result_set.pages = result_set.record_class.paginator.new(result_set, data)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def handle_included(result_set, data)
|
|
97
|
-
result_set.included = IncludedData.new(result_set, data.fetch("included", []))
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
1
|
+
module JsonApiClient
|
|
2
|
+
module Parsers
|
|
3
|
+
class Parser
|
|
4
|
+
class << self
|
|
5
|
+
def parse(klass, response)
|
|
6
|
+
data = response.body.present? ? response.body : {}
|
|
7
|
+
|
|
8
|
+
ResultSet.new.tap do |result_set|
|
|
9
|
+
result_set.record_class = klass
|
|
10
|
+
result_set.uri = response.env[:url]
|
|
11
|
+
handle_json_api(result_set, data)
|
|
12
|
+
handle_data(result_set, data)
|
|
13
|
+
handle_errors(result_set, data)
|
|
14
|
+
handle_meta(result_set, data)
|
|
15
|
+
handle_links(result_set, data)
|
|
16
|
+
handle_relationships(result_set, data)
|
|
17
|
+
handle_pagination(result_set, data)
|
|
18
|
+
handle_included(result_set, data)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
#
|
|
23
|
+
# Given a resource hash, returns a Resource.new friendly hash
|
|
24
|
+
# which flattens the attributes in w/ id and type.
|
|
25
|
+
#
|
|
26
|
+
# Example:
|
|
27
|
+
#
|
|
28
|
+
# Given:
|
|
29
|
+
# {
|
|
30
|
+
# id: 1.
|
|
31
|
+
# type: 'person',
|
|
32
|
+
# attributes: {
|
|
33
|
+
# first_name: 'Jeff',
|
|
34
|
+
# last_name: 'Ching'
|
|
35
|
+
# },
|
|
36
|
+
# links: {...},
|
|
37
|
+
# relationships: {...}
|
|
38
|
+
# }
|
|
39
|
+
#
|
|
40
|
+
# Returns:
|
|
41
|
+
# {
|
|
42
|
+
# id: 1,
|
|
43
|
+
# type: 'person',
|
|
44
|
+
# first_name: 'Jeff',
|
|
45
|
+
# last_name: 'Ching'
|
|
46
|
+
# links: {...},
|
|
47
|
+
# relationships: {...}
|
|
48
|
+
# }
|
|
49
|
+
#
|
|
50
|
+
#
|
|
51
|
+
def parameters_from_resource(params)
|
|
52
|
+
attrs = params.slice('id', 'links', 'meta', 'type', 'relationships')
|
|
53
|
+
attrs.merge(params.fetch('attributes', {}))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def handle_json_api(result_set, data)
|
|
59
|
+
result_set.implementation = Implementation.new(data.fetch("jsonapi", {}))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def handle_data(result_set, data)
|
|
63
|
+
# all data lives under the "data" attribute
|
|
64
|
+
results = data.fetch("data", [])
|
|
65
|
+
|
|
66
|
+
# we will treat everything as an Array
|
|
67
|
+
results = [results] unless results.is_a?(Array)
|
|
68
|
+
resources = results.compact.map do |res|
|
|
69
|
+
resource = result_set.record_class.load(parameters_from_resource(res))
|
|
70
|
+
resource.last_result_set = result_set
|
|
71
|
+
resource
|
|
72
|
+
end
|
|
73
|
+
result_set.concat(resources)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def handle_errors(result_set, data)
|
|
77
|
+
result_set.errors = ErrorCollector.new(data.fetch("errors", []))
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def handle_meta(result_set, data)
|
|
81
|
+
result_set.meta = MetaData.new(data.fetch("meta", {}), result_set.record_class)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def handle_links(result_set, data)
|
|
85
|
+
result_set.links = Linking::TopLevelLinks.new(result_set.record_class, data.fetch("links", {}))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def handle_relationships(result_set, data)
|
|
89
|
+
result_set.relationships = Relationships::TopLevelRelations.new(result_set.record_class, data.fetch("relationships", {}))
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def handle_pagination(result_set, data)
|
|
93
|
+
result_set.pages = result_set.record_class.paginator.new(result_set, data)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def handle_included(result_set, data)
|
|
97
|
+
result_set.included = IncludedData.new(result_set, data.fetch("included", []))
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|