easy-jsonapi 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/publish-gem.yml +60 -0
- data/.github/workflows/rake.yml +35 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +106 -0
- data/LICENSE.txt +21 -0
- data/README.md +209 -0
- data/Rakefile +20 -0
- data/UsingTheRequestObject.md +74 -0
- data/UsingUserConfigurations.md +95 -0
- data/bin/bundle +114 -0
- data/bin/console +15 -0
- data/bin/htmldiff +29 -0
- data/bin/kramdown +29 -0
- data/bin/ldiff +29 -0
- data/bin/license_finder +29 -0
- data/bin/license_finder_pip.py +29 -0
- data/bin/maruku +29 -0
- data/bin/marutex +29 -0
- data/bin/nokogiri +29 -0
- data/bin/racc +29 -0
- data/bin/rackup +29 -0
- data/bin/rake +29 -0
- data/bin/redcarpet +29 -0
- data/bin/reverse_markdown +29 -0
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/bin/ruby-parse +29 -0
- data/bin/ruby-rewrite +29 -0
- data/bin/setup +8 -0
- data/bin/solargraph +29 -0
- data/bin/thor +29 -0
- data/bin/tilt +29 -0
- data/bin/yard +29 -0
- data/bin/yardoc +29 -0
- data/bin/yri +29 -0
- data/easy-jsonapi.gemspec +39 -0
- data/lib/easy/jsonapi.rb +12 -0
- data/lib/easy/jsonapi/collection.rb +144 -0
- data/lib/easy/jsonapi/config_manager.rb +144 -0
- data/lib/easy/jsonapi/config_manager/config.rb +49 -0
- data/lib/easy/jsonapi/document.rb +71 -0
- data/lib/easy/jsonapi/document/error.rb +48 -0
- data/lib/easy/jsonapi/document/error/error_member.rb +15 -0
- data/lib/easy/jsonapi/document/jsonapi.rb +26 -0
- data/lib/easy/jsonapi/document/jsonapi/jsonapi_member.rb +15 -0
- data/lib/easy/jsonapi/document/links.rb +36 -0
- data/lib/easy/jsonapi/document/links/link.rb +15 -0
- data/lib/easy/jsonapi/document/meta.rb +26 -0
- data/lib/easy/jsonapi/document/meta/meta_member.rb +14 -0
- data/lib/easy/jsonapi/document/resource.rb +56 -0
- data/lib/easy/jsonapi/document/resource/attributes.rb +37 -0
- data/lib/easy/jsonapi/document/resource/attributes/attribute.rb +29 -0
- data/lib/easy/jsonapi/document/resource/relationships.rb +40 -0
- data/lib/easy/jsonapi/document/resource/relationships/relationship.rb +50 -0
- data/lib/easy/jsonapi/document/resource_id.rb +28 -0
- data/lib/easy/jsonapi/exceptions.rb +27 -0
- data/lib/easy/jsonapi/exceptions/document_exceptions.rb +619 -0
- data/lib/easy/jsonapi/exceptions/headers_exceptions.rb +156 -0
- data/lib/easy/jsonapi/exceptions/naming_exceptions.rb +36 -0
- data/lib/easy/jsonapi/exceptions/query_params_exceptions.rb +67 -0
- data/lib/easy/jsonapi/exceptions/user_defined_exceptions.rb +253 -0
- data/lib/easy/jsonapi/field.rb +43 -0
- data/lib/easy/jsonapi/header_collection.rb +38 -0
- data/lib/easy/jsonapi/header_collection/header.rb +11 -0
- data/lib/easy/jsonapi/item.rb +88 -0
- data/lib/easy/jsonapi/middleware.rb +158 -0
- data/lib/easy/jsonapi/name_value_pair.rb +72 -0
- data/lib/easy/jsonapi/name_value_pair_collection.rb +78 -0
- data/lib/easy/jsonapi/parser.rb +38 -0
- data/lib/easy/jsonapi/parser/document_parser.rb +196 -0
- data/lib/easy/jsonapi/parser/headers_parser.rb +33 -0
- data/lib/easy/jsonapi/parser/rack_req_params_parser.rb +117 -0
- data/lib/easy/jsonapi/request.rb +40 -0
- data/lib/easy/jsonapi/request/query_param_collection.rb +56 -0
- data/lib/easy/jsonapi/request/query_param_collection/fields_param.rb +32 -0
- data/lib/easy/jsonapi/request/query_param_collection/fields_param/fieldset.rb +34 -0
- data/lib/easy/jsonapi/request/query_param_collection/filter_param.rb +28 -0
- data/lib/easy/jsonapi/request/query_param_collection/filter_param/filter.rb +34 -0
- data/lib/easy/jsonapi/request/query_param_collection/include_param.rb +119 -0
- data/lib/easy/jsonapi/request/query_param_collection/page_param.rb +55 -0
- data/lib/easy/jsonapi/request/query_param_collection/query_param.rb +47 -0
- data/lib/easy/jsonapi/request/query_param_collection/sort_param.rb +25 -0
- data/lib/easy/jsonapi/response.rb +22 -0
- data/lib/easy/jsonapi/utility.rb +158 -0
- data/lib/easy/jsonapi/version.rb +8 -0
- metadata +248 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'easy/jsonapi/request/query_param_collection/query_param'
|
4
|
+
|
5
|
+
module JSONAPI
|
6
|
+
class Request
|
7
|
+
class QueryParamCollection < JSONAPI::NameValuePairCollection
|
8
|
+
# Used to create a unique Fieldset JSONAPI::Request::QueryParamCollection::QueryParam
|
9
|
+
class FieldsParam < QueryParam
|
10
|
+
|
11
|
+
# @param fieldset_arr [Array<JSONAPI::Request::QueryParamCollection::FieldsParam::Fieldset>]
|
12
|
+
# The array of fieldsets found in the query string. Ex: fields[resource]=res_field1,res_field2
|
13
|
+
def initialize(fieldset_arr)
|
14
|
+
super('fields', fieldset_arr)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Alias to parent #value method
|
18
|
+
# @return [Array<JSONAPI::Request::QueryParamCollection::FieldsParam::Fieldset>]
|
19
|
+
def fieldsets
|
20
|
+
value
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return The the query string representation of the included fieldsets
|
24
|
+
# ex: "#{fieldset1.to_s}&{fieldset2.to_s}&..."
|
25
|
+
def to_s
|
26
|
+
JSONAPI::Utility.to_string_collection(value, delimiter: '&')
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'easy/jsonapi/name_value_pair_collection'
|
4
|
+
require 'easy/jsonapi/request/query_param_collection/fields_param'
|
5
|
+
require 'easy/jsonapi/utility'
|
6
|
+
|
7
|
+
module JSONAPI
|
8
|
+
class Request
|
9
|
+
class QueryParamCollection < NameValuePairCollection
|
10
|
+
class FieldsParam < QueryParam
|
11
|
+
# Collection of fields related to specific resource objects
|
12
|
+
class Fieldset
|
13
|
+
|
14
|
+
attr_reader :resource_type, :fields
|
15
|
+
|
16
|
+
# @param field_arr [Array<JSONAPI::Field>]
|
17
|
+
# A fieldset is a collection of Resource Fields
|
18
|
+
def initialize(resource_type, field_arr = [])
|
19
|
+
@resource_type = resource_type
|
20
|
+
@fields = field_arr
|
21
|
+
end
|
22
|
+
|
23
|
+
# Represention of Fieldset as a string where fields
|
24
|
+
# are comma separated strings
|
25
|
+
def to_s
|
26
|
+
pre_string = "fields[#{@resource_type}]="
|
27
|
+
JSONAPI::Utility.to_string_collection(@fields, delimiter: ',', pre_string: pre_string)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'easy/jsonapi/request/query_param_collection/query_param'
|
4
|
+
require 'easy/jsonapi/utility'
|
5
|
+
|
6
|
+
module JSONAPI
|
7
|
+
class Request
|
8
|
+
class QueryParamCollection < JSONAPI::NameValuePairCollection
|
9
|
+
|
10
|
+
# Used to create a unique Filter JSONAPI::Request::QueryParamCollection::QueryParam
|
11
|
+
class FilterParam < QueryParam
|
12
|
+
|
13
|
+
# @param filter_arr [Array<JSONAPI::Request::QueryParamCollection::FilterParam::Filter>]
|
14
|
+
# The array of filters included in the query string. Ex: filter[articles]=(posted_date == today)
|
15
|
+
def initialize(filter_arr)
|
16
|
+
super('filters', filter_arr)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Represent each filter separated by a & value
|
20
|
+
# Ex: "#{filter1.to_s}&{filter2.to_s}&..."
|
21
|
+
def to_s
|
22
|
+
JSONAPI::Utility.to_string_collection(value, delimiter: '&')
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'easy/jsonapi/request/query_param_collection/filter_param'
|
4
|
+
|
5
|
+
module JSONAPI
|
6
|
+
class Request
|
7
|
+
class QueryParamCollection < NameValuePairCollection
|
8
|
+
class FilterParam < QueryParam
|
9
|
+
# Represents an individual Filtering scheme for the filter query param(s) used.
|
10
|
+
class Filter
|
11
|
+
|
12
|
+
attr_reader :resource_type, :filter
|
13
|
+
|
14
|
+
# @param resource_type [String] The type to filter
|
15
|
+
# @param filter [String] The filter algorithm
|
16
|
+
def initialize(resource_type, filter)
|
17
|
+
@resource_type = resource_type
|
18
|
+
@filter = filter
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [String] The value of the filter
|
22
|
+
def value
|
23
|
+
@filter
|
24
|
+
end
|
25
|
+
|
26
|
+
# Represent filter as an individual filter query param
|
27
|
+
def to_s
|
28
|
+
"filter[#{@resource_type}]=#{@filter}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'easy/jsonapi/request/query_param_collection/query_param'
|
4
|
+
require 'easy/jsonapi/utility'
|
5
|
+
|
6
|
+
module JSONAPI
|
7
|
+
class Request
|
8
|
+
class QueryParamCollection < JSONAPI::NameValuePairCollection
|
9
|
+
# The include query param
|
10
|
+
class IncludeParam < QueryParam
|
11
|
+
|
12
|
+
|
13
|
+
# @param includes_arr [Array<String>] An array with each individual query include
|
14
|
+
# Ex: incude=author,people => ['author', 'people']
|
15
|
+
def initialize(includes_arr)
|
16
|
+
includes_hash_structure = store_includes(includes_arr)
|
17
|
+
super('includes', includes_hash_structure)
|
18
|
+
end
|
19
|
+
|
20
|
+
# to string
|
21
|
+
def to_s
|
22
|
+
"include=#{stringify_includes_hash(value)}"
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Represent include internal hash as query string
|
28
|
+
# @param includes_hash [Hash] The internal structure
|
29
|
+
def stringify_includes_hash(includes_hash)
|
30
|
+
to_return = ''
|
31
|
+
first = true
|
32
|
+
includes_hash.each do |mem_name, mem_hash|
|
33
|
+
if first
|
34
|
+
to_return += to_s_mem(mem_name, mem_hash)
|
35
|
+
first = false
|
36
|
+
else
|
37
|
+
to_return += ",#{to_s_mem(mem_name, mem_hash)}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
to_return
|
41
|
+
end
|
42
|
+
|
43
|
+
# Depending on the delimiter stringify differently.
|
44
|
+
# @param mem_name [Symbol] The name of the member to stringify
|
45
|
+
# @param mem_hash [Hash] The information about that member
|
46
|
+
def to_s_mem(mem_name, mem_hash)
|
47
|
+
if mem_hash[:relationships] == {}
|
48
|
+
mem_name.to_s
|
49
|
+
else
|
50
|
+
delimiter = mem_hash[:included] == true ? '.' : '-'
|
51
|
+
prefix = "#{mem_name}#{delimiter}"
|
52
|
+
to_return = ''
|
53
|
+
first = true
|
54
|
+
mem_hash[:relationships].each do |m_name, m_hash|
|
55
|
+
if first
|
56
|
+
to_return += "#{prefix}#{to_s_mem(m_name, m_hash)}"
|
57
|
+
first = false
|
58
|
+
else
|
59
|
+
to_return += ",#{prefix}#{to_s_mem(m_name, m_hash)}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
to_return
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Helper for #initialize
|
67
|
+
# @param includes_arr [Array<String>] The array of includes to store
|
68
|
+
def store_includes(includes_arr)
|
69
|
+
incl_hash = {}
|
70
|
+
includes_arr.each do |include_str|
|
71
|
+
include_str_arr = include_str.scan(/\w+|-|\./) # split into array (word, -, or .)
|
72
|
+
store_include(incl_hash, include_str_arr)
|
73
|
+
end
|
74
|
+
incl_hash
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param loc_in_h [Hash] The location within the main hash
|
78
|
+
# @param i_arr [Array<String>] The array of include strings
|
79
|
+
def store_include(loc_in_h, i_arr)
|
80
|
+
res_name = i_arr[0].to_sym
|
81
|
+
if i_arr.length == 1
|
82
|
+
add_member(loc_in_h, res_name, included: true)
|
83
|
+
else
|
84
|
+
add_member(loc_in_h, res_name, included: res_included?(i_arr))
|
85
|
+
store_include(loc_in_h[res_name][:relationships], i_arr[2..])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @param (see #store_include)
|
90
|
+
def res_included?(i_arr)
|
91
|
+
delim = i_arr[1]
|
92
|
+
case delim
|
93
|
+
when '.'
|
94
|
+
true
|
95
|
+
when '-'
|
96
|
+
false
|
97
|
+
else
|
98
|
+
raise 'Syntax Error in include query string query param'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# @param loc_in_h [Hash] The location within the main hash
|
103
|
+
# @param res_name [Symbol] The name of the resource
|
104
|
+
# @param included [TrueClass | FalseClass] Whether or not a resource
|
105
|
+
# is being requested or not
|
106
|
+
def add_member(loc_in_h, res_name, included:)
|
107
|
+
if loc_in_h.key?(res_name)
|
108
|
+
loc_in_h[res_name][:included] = included unless included == false
|
109
|
+
else
|
110
|
+
loc_in_h[res_name] = {
|
111
|
+
included: included,
|
112
|
+
relationships: {}
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'easy/jsonapi/request/query_param_collection/query_param'
|
4
|
+
|
5
|
+
module JSONAPI
|
6
|
+
class Request
|
7
|
+
class QueryParamCollection < JSONAPI::NameValuePairCollection
|
8
|
+
# Used to create a unique Page JSONAPI::Request::QueryParamCollection::QueryParam
|
9
|
+
class PageParam < QueryParam
|
10
|
+
|
11
|
+
# @param offset [Integer | String] the page offset
|
12
|
+
# @param limit [Integer | String] the # of resources returned on a given page
|
13
|
+
def initialize(offset:, limit:)
|
14
|
+
super('page', { offset: offset.to_i, limit: limit.to_i })
|
15
|
+
end
|
16
|
+
|
17
|
+
# @raise [RuntimeError] Informs user to use a different method
|
18
|
+
def value
|
19
|
+
raise 'PageParam does not provide a #value method, try #offset or #limit instead'
|
20
|
+
end
|
21
|
+
|
22
|
+
# @raise [RuntimeError] Informs user to use a different method
|
23
|
+
def value=(_)
|
24
|
+
raise 'PageParam does not provide a #value= method, try #offset= or #limit= instead'
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Integer] The page offset
|
28
|
+
def offset
|
29
|
+
@item[:value][:offset]
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param new_offset [Integer | String] The new page offset number
|
33
|
+
def offset=(new_offset)
|
34
|
+
@item[:value][:offset] = new_offset.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Integer] The # of resources returned on a given page
|
38
|
+
def limit
|
39
|
+
@item[:value][:limit]
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param new_limit [Integer] The new page limit number
|
43
|
+
def limit=(new_limit)
|
44
|
+
@item[:value][:limit] = new_limit.to_i
|
45
|
+
end
|
46
|
+
|
47
|
+
# Represents the Page class in a string format
|
48
|
+
def to_s
|
49
|
+
"page[offset]=#{offset}&page[limit]=#{limit}"
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'easy/jsonapi/request/query_param_collection'
|
4
|
+
require 'easy/jsonapi/name_value_pair'
|
5
|
+
require 'easy/jsonapi/exceptions/query_params_exceptions'
|
6
|
+
require 'easy/jsonapi/utility'
|
7
|
+
|
8
|
+
|
9
|
+
module JSONAPI
|
10
|
+
class Request
|
11
|
+
class QueryParamCollection < JSONAPI::NameValuePairCollection
|
12
|
+
# A generic name=value query parameter
|
13
|
+
class QueryParam < JSONAPI::NameValuePair
|
14
|
+
|
15
|
+
# @param name [String] The name of the parameter
|
16
|
+
# @param value [String | Array<String>] The value of the parameter
|
17
|
+
def initialize(name, value)
|
18
|
+
if instance_of?(QueryParam)
|
19
|
+
JSONAPI::Exceptions::QueryParamsExceptions.check_param_name(name)
|
20
|
+
end
|
21
|
+
value = value.split(',') if value.is_a? String
|
22
|
+
super(name, value)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Update the query_param value, turning value into an array if it was given as a string
|
26
|
+
# @param new_value [String, Array<String>] The new value of the Parameter
|
27
|
+
def value=(new_value)
|
28
|
+
new_value = new_value.split(',') if new_value.is_a? String
|
29
|
+
super(new_value)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Represents a parameter as a string
|
33
|
+
def to_s
|
34
|
+
"#{name}=#{JSONAPI::Utility.to_string_collection(value, delimiter: ',')}"
|
35
|
+
end
|
36
|
+
|
37
|
+
# @raise RuntimeError Cannot change the name of a QueryParam object
|
38
|
+
def name=(_)
|
39
|
+
raise 'Cannot change the name of QueryParam Objects'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# include=author,comments-likers,comments.likes
|
47
|
+
# author comments-likers comments.likes
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'easy/jsonapi/request/query_param_collection/query_param'
|
4
|
+
|
5
|
+
module JSONAPI
|
6
|
+
class Request
|
7
|
+
class QueryParamCollection < JSONAPI::NameValuePairCollection
|
8
|
+
# Used to create a unique Sort JSONAPI::Request::QueryParamCollection::QueryParam
|
9
|
+
class SortParam < QueryParam
|
10
|
+
|
11
|
+
# @param res_field_arr [Array<JSONAPI::Field] The resource fields
|
12
|
+
# to sort the primary resources by.
|
13
|
+
def initialize(res_field_arr)
|
14
|
+
super('sorts', res_field_arr)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Represent sort as query string
|
18
|
+
def to_s
|
19
|
+
"sort=#{JSONAPI::Utility.to_string_collection(value, delimiter: ',')}"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'easy/jsonapi/exceptions'
|
4
|
+
|
5
|
+
module JSONAPI
|
6
|
+
# Used to validate the serialized response before returned to a client
|
7
|
+
module Response
|
8
|
+
# TODO: Add config_manager options for out bound serialization validation
|
9
|
+
|
10
|
+
# @param headers [Hash] The hash of response headers.
|
11
|
+
# @param body [Hash | String] The ruby hash mimicking jsonapi or
|
12
|
+
# a JSON document to check for compliance
|
13
|
+
# @return [Nilclass] if no errors are found
|
14
|
+
# @raise [InvalidDocument | InvalidHeader] depending on what errors were found
|
15
|
+
def self.validate(headers, body)
|
16
|
+
# TODO: Spec checks based on collections which can be refered from the location header
|
17
|
+
# returned by the server
|
18
|
+
JSONAPI::Exceptions::HeadersExceptions.check_compliance(headers.transform_keys(&:to_s).transform_keys(&:upcase))
|
19
|
+
JSONAPI::Exceptions::DocumentExceptions.check_compliance(body)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JSONAPI
|
4
|
+
|
5
|
+
# A collection of resued logic throughout the gem.
|
6
|
+
module Utility
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# To hash method for a JSONAPI collection (like Attributes)
|
11
|
+
# @param collection [Inumerable] The collection to hashify
|
12
|
+
def to_h_collection(collection)
|
13
|
+
to_return = {}
|
14
|
+
collection.each do |mem|
|
15
|
+
h_val = JSONAPI::Utility.to_h_value(mem)
|
16
|
+
to_return[mem.name.to_sym] = h_val
|
17
|
+
end
|
18
|
+
to_return
|
19
|
+
end
|
20
|
+
|
21
|
+
# Helper method for #to_h_collection
|
22
|
+
# @param val [Any] The value to call to hash on.
|
23
|
+
# @return a hash value member
|
24
|
+
def to_h_value(val)
|
25
|
+
case val
|
26
|
+
when String
|
27
|
+
val
|
28
|
+
when JSONAPI::Collection
|
29
|
+
obj_hash = {}
|
30
|
+
val.each { |i| obj_hash[i.name.to_sym] = to_h_value(i) }
|
31
|
+
obj_hash
|
32
|
+
else
|
33
|
+
v = val.value
|
34
|
+
case v
|
35
|
+
when String
|
36
|
+
to_h_value(v)
|
37
|
+
when Array
|
38
|
+
v.map { |e| to_h_value(e) }
|
39
|
+
else
|
40
|
+
v.to_h
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Helper for #to_h for classes that arent collection and have a set number
|
46
|
+
# of instance variables to hashify
|
47
|
+
# @param hash_to_add_to [Hash] The hash to return
|
48
|
+
# @param obj_member [Any] The instance variable to hashify
|
49
|
+
# @param obj_member_name [Symbol] The hash key to store the object under
|
50
|
+
# @return [Hash] The hash for a specific instance variable
|
51
|
+
def to_h_member(hash_to_add_to, obj_member, obj_member_name)
|
52
|
+
return if obj_member.nil?
|
53
|
+
case obj_member
|
54
|
+
when String
|
55
|
+
hash_to_add_to[obj_member_name] = obj_member
|
56
|
+
when Array
|
57
|
+
hash_arr = obj_member.map(&:to_h)
|
58
|
+
hash_to_add_to[obj_member_name] = hash_arr
|
59
|
+
else
|
60
|
+
hash_to_add_to[obj_member_name] = obj_member.to_h
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Helper method for #to_s that stringifys a collection
|
65
|
+
# @param collection [Inumerable] An array type of collection
|
66
|
+
# @param delimiter [String] The delimieter to separate each item string
|
67
|
+
# @param pre_string [String] The string to precede the collection string
|
68
|
+
# @param post_string [String] The string to follow the collection
|
69
|
+
def to_string_collection(collection, delimiter: ', ', pre_string: '', post_string: '')
|
70
|
+
to_return = pre_string
|
71
|
+
first = true
|
72
|
+
collection.each do |item|
|
73
|
+
if first
|
74
|
+
to_return += item.to_s
|
75
|
+
first = false
|
76
|
+
else
|
77
|
+
to_return += "#{delimiter}#{item}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
to_return += post_string
|
81
|
+
end
|
82
|
+
|
83
|
+
# Helper for #to_s where collections are hashes and members should not
|
84
|
+
# be included if they are nil. It also accounts for arrays.
|
85
|
+
# @param str_name [String | Symbol] The name of hash member
|
86
|
+
# @param member [Any] The value of the hash member
|
87
|
+
# @param first_member [TrueClass | FalseClass] Whether or not this is the
|
88
|
+
# first member in the hash.
|
89
|
+
def member_to_s(str_name, member, first_member: false)
|
90
|
+
return '' if member.nil?
|
91
|
+
member = "\"#{member}\"" if member.is_a? String
|
92
|
+
if first_member
|
93
|
+
"\"#{str_name}\": #{array_to_s(member)}"
|
94
|
+
else
|
95
|
+
", \"#{str_name}\": #{array_to_s(member)}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the proper to_s for members regardless of
|
100
|
+
# whether they are stored as an array or member object
|
101
|
+
def array_to_s(obj_arr)
|
102
|
+
return obj_arr.to_s unless obj_arr.is_a? Array
|
103
|
+
to_return = '['
|
104
|
+
first = true
|
105
|
+
obj_arr.each do |obj|
|
106
|
+
if first
|
107
|
+
to_return += obj.to_s
|
108
|
+
first = false
|
109
|
+
else
|
110
|
+
to_return += ", #{obj}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
to_return += ']'
|
114
|
+
end
|
115
|
+
|
116
|
+
# Get resource type from path
|
117
|
+
# @param path [String] The url path
|
118
|
+
# @return [String] The resource type
|
119
|
+
def path_to_res_type(path)
|
120
|
+
path_arr = path.split('/')
|
121
|
+
if integer?(path_arr[-1]) || uuid?(path_arr[-1])
|
122
|
+
path_arr[-2]
|
123
|
+
else
|
124
|
+
path_arr[-1]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Check if an input is an integer
|
129
|
+
# @param str [String | Integer]
|
130
|
+
def integer?(str)
|
131
|
+
# integers cannot be valid symbols, so assume string or integer input
|
132
|
+
return true if str.is_a?(Integer) ||
|
133
|
+
str =~ /\A\d+\z/
|
134
|
+
false
|
135
|
+
end
|
136
|
+
|
137
|
+
# Use regix to test whether the input is a valid gen 4 uuid.
|
138
|
+
# @param uuid [String]
|
139
|
+
# @return [TrueClass | FalseClass]
|
140
|
+
def uuid?(uuid)
|
141
|
+
# uuids cannot be valid symbols, so assume string
|
142
|
+
return true if uuid =~ /\A[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\z/i ||
|
143
|
+
uuid =~ /\A[\dA-F]{8}-[\dA-F]{4}-[\dA-F]{4}-[\dA-F]{4}-[\dA-F]{12}\z/i
|
144
|
+
false
|
145
|
+
end
|
146
|
+
|
147
|
+
# The hash method #dig throws an error if an array appears in the path specified,
|
148
|
+
# this method returns false for such a senario.
|
149
|
+
# @param hash [Hash] The hash being inspected
|
150
|
+
# @param args [Array<Symbol | String>] The hash keys making up the path
|
151
|
+
def all_hash_path?(hash, args)
|
152
|
+
return false if (args.size.positive? && !hash.is_a?(Hash)) || hash.nil?
|
153
|
+
return true if args.size.zero? && !hash.nil?
|
154
|
+
all_hash_path?(hash[args.first], args[1..])
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|