jsonapi_helpers 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/{README.MD → README.md} +0 -0
- data/Rakefile +8 -0
- data/jsonapi_helpers.gemspec +34 -0
- data/lib/jsonapi_helpers.rb +69 -0
- data/lib/jsonapi_helpers/params/fields.rb +22 -0
- data/lib/jsonapi_helpers/params/filter.rb +44 -0
- data/lib/jsonapi_helpers/params/includes.rb +18 -0
- data/lib/jsonapi_helpers/params/sort.rb +27 -0
- data/lib/jsonapi_helpers/serializers/data.rb +53 -0
- data/lib/jsonapi_helpers/serializers/datum.rb +26 -0
- data/lib/jsonapi_helpers/serializers/deserializer.rb +14 -0
- data/lib/jsonapi_helpers/serializers/error.rb +55 -0
- data/lib/jsonapi_helpers/serializers/errors.rb +36 -0
- data/lib/jsonapi_helpers/serializers/model.rb +67 -0
- data/lib/jsonapi_helpers/serializers/model_error.rb +71 -0
- data/lib/jsonapi_helpers/serializers/relationships.rb +27 -0
- data/lib/jsonapi_helpers/support/key_transform.rb +75 -0
- data/lib/jsonapi_helpers/support/string_support.rb +23 -0
- data/lib/jsonapi_helpers/version.rb +2 -2
- metadata +23 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7c7204fad99ba81fb2677c0bcaf99655ca3991b
|
4
|
+
data.tar.gz: a2e3a050fee11dea4c56c4caa8f51602204db2c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b6897227e38470925b03f6d5747556abee220ddaf689b1345795d06e25117cd70df3ee507b158be04d20ee4378cdeca4f24b79e60a1cff57c59ee9f707c96cc
|
7
|
+
data.tar.gz: 4a866970c77fe525ee3486b6180353cd867fc8d31654202cff3eaba0f893666bc45907c4c8f351c5a147ea61de7438bdf0ed1709f8faa9e2cc4353f0980f27ae
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/{README.MD → README.md}
RENAMED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
lib = File.expand_path('../lib', __FILE__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
require 'jsonapi_helpers/version'
|
7
|
+
|
8
|
+
Gem::Specification.new do |spec|
|
9
|
+
spec.name = 'jsonapi_helpers'
|
10
|
+
spec.version = JSONAPIHelpers::VERSION
|
11
|
+
spec.authors = ['Jacob Burenstam']
|
12
|
+
spec.email = ['burenstam@gmail.com']
|
13
|
+
|
14
|
+
spec.summary = 'A set of helpers for generating JSON API compliant responses.'
|
15
|
+
spec.description = 'A set of helpers for generating JSON API compliant responses with together with the active_model_serializers gem.' # rubocop:disable Metrics/LineLength
|
16
|
+
spec.homepage = 'https://github.com/buren/jsonapi_helpers'
|
17
|
+
spec.license = 'MIT'
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
20
|
+
f.match(%r{^(test|spec|features)/})
|
21
|
+
end
|
22
|
+
spec.bindir = 'exe'
|
23
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
|
+
spec.require_paths = ['lib']
|
25
|
+
|
26
|
+
spec.add_dependency 'activesupport', '>= 4.2'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'active_model_serializers', '~> 0.10'
|
29
|
+
spec.add_development_dependency 'activemodel', '>= 4.2'
|
30
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
31
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
32
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
33
|
+
spec.add_development_dependency 'byebug', '~> 9.0'
|
34
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/object/json'
|
4
|
+
|
5
|
+
# Local requires
|
6
|
+
require 'jsonapi_helpers/version'
|
7
|
+
|
8
|
+
require 'jsonapi_helpers/support/key_transform'
|
9
|
+
require 'jsonapi_helpers/support/string_support'
|
10
|
+
|
11
|
+
require 'jsonapi_helpers/serializers/deserializer'
|
12
|
+
require 'jsonapi_helpers/serializers/model'
|
13
|
+
require 'jsonapi_helpers/serializers/model_error'
|
14
|
+
require 'jsonapi_helpers/serializers/data'
|
15
|
+
require 'jsonapi_helpers/serializers/datum'
|
16
|
+
require 'jsonapi_helpers/serializers/error'
|
17
|
+
require 'jsonapi_helpers/serializers/errors'
|
18
|
+
|
19
|
+
require 'jsonapi_helpers/params/fields'
|
20
|
+
require 'jsonapi_helpers/params/filter'
|
21
|
+
require 'jsonapi_helpers/params/includes'
|
22
|
+
require 'jsonapi_helpers/params/sort'
|
23
|
+
|
24
|
+
module JSONAPIHelpers
|
25
|
+
class << self
|
26
|
+
attr_accessor :config
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.configure
|
30
|
+
self.config ||= Configuration.new
|
31
|
+
block_given? ? yield(config) : config
|
32
|
+
config
|
33
|
+
end
|
34
|
+
|
35
|
+
class Configuration
|
36
|
+
KEY_TRANSFORMS = %i(dash camel camel_lower underscore unaltered).freeze
|
37
|
+
|
38
|
+
attr_reader :key_transform
|
39
|
+
attr_writer :deserializer_klass, :params_klass
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
@key_transform = :unaltered
|
43
|
+
@deserializer_klass = nil
|
44
|
+
@params_klass = nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def key_transform=(key_transform)
|
48
|
+
type = key_transform.to_sym
|
49
|
+
unknown_key_transform!(type) unless KEY_TRANSFORMS.include?(type)
|
50
|
+
|
51
|
+
@key_transform = type
|
52
|
+
end
|
53
|
+
|
54
|
+
def deserializer_klass
|
55
|
+
@deserializer_klass || fail('deserializer_klass must be set, e.g: ActiveModelSerializers::Deserialization') # rubocop:disable Metrics/LineLength
|
56
|
+
end
|
57
|
+
|
58
|
+
def params_klass
|
59
|
+
@params_klass || fail('params_klass must be set, e.g: ActionController::Parameters')
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def unknown_key_transform!(type)
|
65
|
+
types = KEY_TRANSFORMS.join(', ')
|
66
|
+
fail(ArgumentError, "Unknown key transform type '#{type}', known types: #{types}")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JSONAPIHelpers
|
4
|
+
module Params
|
5
|
+
class Fields
|
6
|
+
attr_reader :fields_params
|
7
|
+
|
8
|
+
def initialize(fields_params)
|
9
|
+
@fields_params = {}
|
10
|
+
(fields_params || {}).each do |model_name, value|
|
11
|
+
@fields_params[model_name] = value.split(',').map do |name|
|
12
|
+
StringSupport.underscore(name.strip)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_h
|
18
|
+
fields_params
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module JSONAPIHelpers
|
6
|
+
module Params
|
7
|
+
module Filter
|
8
|
+
def self.build(filters, allowed, transform = {})
|
9
|
+
return {} if filters.nil? || filters.is_a?(String)
|
10
|
+
|
11
|
+
filtered = {}
|
12
|
+
filters.each do |key, value|
|
13
|
+
key_sym = StringSupport.underscore(key).to_sym
|
14
|
+
if allowed.include?(key_sym)
|
15
|
+
filtered[key_sym] = format_value(value, transform[key_sym])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
filtered
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.format_value(value, type)
|
22
|
+
case type
|
23
|
+
when :date_range
|
24
|
+
format_date_range(value)
|
25
|
+
else
|
26
|
+
value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.format_date_range(value)
|
31
|
+
date_parts = value.split('..')
|
32
|
+
start = _parse_date_string(date_parts.first)
|
33
|
+
finish = _parse_date_string(date_parts.last)
|
34
|
+
start..finish
|
35
|
+
rescue ArgumentError
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def self._parse_date_string(string)
|
40
|
+
Date.parse(string, false)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JSONAPIHelpers
|
4
|
+
module Params
|
5
|
+
class Includes
|
6
|
+
attr_reader :include_param
|
7
|
+
|
8
|
+
def initialize(include_param)
|
9
|
+
@include_param = StringSupport.underscore(include_param || '')
|
10
|
+
end
|
11
|
+
|
12
|
+
def permit(*permitted_includes)
|
13
|
+
include_array = include_param.split(',')
|
14
|
+
include_array & permitted_includes.flatten(1)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JSONAPIHelpers
|
4
|
+
module Params
|
5
|
+
module Sort
|
6
|
+
def self.build(sort, allowed, default)
|
7
|
+
allowed = allowed.map(&:to_s)
|
8
|
+
fields = sort.to_s.split(',')
|
9
|
+
|
10
|
+
ordered_fields = convert_to_ordered_hash(fields)
|
11
|
+
filtered_fields = ordered_fields.select { |key, _value| allowed.include?(key) }
|
12
|
+
filtered_fields.empty? ? default : filtered_fields
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.convert_to_ordered_hash(fields)
|
16
|
+
fields.each_with_object({}) do |field, hash|
|
17
|
+
if field.start_with?('-')
|
18
|
+
field = StringSupport.underscore(field[1..-1])
|
19
|
+
hash[field] = :desc
|
20
|
+
else
|
21
|
+
hash[StringSupport.underscore(field)] = :asc
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/hash/keys'
|
4
|
+
require 'jsonapi_helpers/serializers/relationships'
|
5
|
+
|
6
|
+
module JSONAPIHelpers
|
7
|
+
module Serializers
|
8
|
+
class Data
|
9
|
+
def initialize(
|
10
|
+
id:,
|
11
|
+
type:,
|
12
|
+
attributes: {},
|
13
|
+
meta: {},
|
14
|
+
relationships: nil,
|
15
|
+
key_transform: JSONAPIHelpers.config.key_transform
|
16
|
+
)
|
17
|
+
@id = id
|
18
|
+
@type = type
|
19
|
+
@attributes = attributes
|
20
|
+
@meta = meta
|
21
|
+
@relationships = relationships
|
22
|
+
@key_transform = key_transform
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_h(shallow: false)
|
26
|
+
data = {
|
27
|
+
id: @id,
|
28
|
+
type: KeyTransform.call(@type.to_s, key_transform: @key_transform),
|
29
|
+
attributes: KeyTransform.call(@attributes, key_transform: @key_transform)
|
30
|
+
}
|
31
|
+
|
32
|
+
if @relationships
|
33
|
+
data[:relationships] = KeyTransform.call(
|
34
|
+
@relationships.to_h,
|
35
|
+
key_transform: @key_transform
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
if shallow
|
40
|
+
data
|
41
|
+
else
|
42
|
+
{ data: data, meta: @meta }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Rails is awkward and calls #to_json with a context argument
|
47
|
+
# NOTE: Rails only method Hash#to_json
|
48
|
+
def to_json(_context = nil)
|
49
|
+
to_h.to_json
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JSONAPIHelpers
|
4
|
+
module Serializers
|
5
|
+
class Datum
|
6
|
+
def initialize(jsonapi_datums)
|
7
|
+
@datums = jsonapi_datums
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_h
|
11
|
+
{
|
12
|
+
data: @datums.map { |data| data.to_h(shallow: true) },
|
13
|
+
meta: {
|
14
|
+
total: @datums.length
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
# Rails is awkward and calls #to_json with a context argument
|
20
|
+
# NOTE: Rails only method Hash#to_json
|
21
|
+
def to_json(_context = nil)
|
22
|
+
to_h.to_json
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JSONAPIHelpers
|
4
|
+
module Serializers
|
5
|
+
module Deserializer
|
6
|
+
def self.parse(params)
|
7
|
+
# Parse the params hash and "flatten" the structure
|
8
|
+
parsed_params = JSONAPIHelpers.config.deserializer_klass.jsonapi_parse(params)
|
9
|
+
# Pass the hash to a params klass where normal whitelisting of params can be made
|
10
|
+
JSONAPIHelpers.config.params_klass.new(parsed_params || {})
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JSONAPIHelpers
|
4
|
+
module Serializers
|
5
|
+
class Error
|
6
|
+
attr_reader :status, :detail, :code
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
detail:,
|
10
|
+
status: 422,
|
11
|
+
code: nil,
|
12
|
+
pointer: nil,
|
13
|
+
attribute: nil,
|
14
|
+
key_transform: JSONAPIHelpers.config.key_transform
|
15
|
+
)
|
16
|
+
@status = status
|
17
|
+
@detail = detail
|
18
|
+
@pointer = pointer(
|
19
|
+
pointer: pointer,
|
20
|
+
attribute: attribute,
|
21
|
+
key_transform: key_transform
|
22
|
+
)
|
23
|
+
@code = code
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_h
|
27
|
+
response = { status: @status, detail: @detail }
|
28
|
+
response[:code] = @code unless @code.nil?
|
29
|
+
response.merge!(@pointer)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def pointer(pointer:, attribute:, key_transform:)
|
35
|
+
return {} if pointer.nil? && attribute.nil?
|
36
|
+
|
37
|
+
full_pointer = if pointer
|
38
|
+
pointer
|
39
|
+
else
|
40
|
+
attribute_pointer(attribute, key_transform: key_transform)
|
41
|
+
end
|
42
|
+
{
|
43
|
+
source: {
|
44
|
+
pointer: full_pointer
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def attribute_pointer(attribute, key_transform:)
|
50
|
+
attribute_name = KeyTransform.call(attribute.to_s, key_transform: key_transform)
|
51
|
+
"/data/attributes/#{attribute_name}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JSONAPIHelpers
|
4
|
+
module Serializers
|
5
|
+
class Errors
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@errors = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(**args)
|
13
|
+
@errors << Error.new(**args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def each(&block)
|
17
|
+
@errors.each(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def length
|
21
|
+
@errors.length
|
22
|
+
end
|
23
|
+
alias_method :size, :length
|
24
|
+
|
25
|
+
def to_h
|
26
|
+
{ errors: @errors.map(&:to_h) }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Rails is awkward and calls #to_json with a context argument
|
30
|
+
# NOTE: Rails only method Hash#to_json
|
31
|
+
def to_json(_context = nil)
|
32
|
+
to_h.to_json
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jsonapi_helpers/action_dispatch_request_wrapper'
|
4
|
+
|
5
|
+
module JSONAPIHelpers
|
6
|
+
module Serializers
|
7
|
+
class Model
|
8
|
+
attr_reader :serializer, :included, :fields, :current_user, :current_language, :model_scope, :meta, :request, :key_transform # rubocop:disable Metrics/LineLength
|
9
|
+
|
10
|
+
def self.serialize(*args)
|
11
|
+
new(*args).serialize
|
12
|
+
end
|
13
|
+
|
14
|
+
# private
|
15
|
+
|
16
|
+
def initialize(
|
17
|
+
model_scope,
|
18
|
+
included: [],
|
19
|
+
fields: {},
|
20
|
+
current_user: nil,
|
21
|
+
current_language: nil,
|
22
|
+
meta: {},
|
23
|
+
request: nil,
|
24
|
+
key_transform: JSONAPIHelpers.config.key_transform
|
25
|
+
)
|
26
|
+
@model_scope = model_scope
|
27
|
+
@included = included
|
28
|
+
@fields = fields
|
29
|
+
@meta = meta
|
30
|
+
@current_user = current_user
|
31
|
+
@current_language = current_language
|
32
|
+
@key_transform = key_transform
|
33
|
+
# NOTE: ActiveModel::Serializer#serializer_for is from active_model_serializers
|
34
|
+
@serializer = ActiveModel::Serializer.serializer_for(model_scope)
|
35
|
+
@request = ActionDispatchRequestWrapper.new(request)
|
36
|
+
end
|
37
|
+
|
38
|
+
def serializer_instance
|
39
|
+
serializer_options = {
|
40
|
+
scope: {
|
41
|
+
current_user: current_user,
|
42
|
+
current_language: current_language,
|
43
|
+
current_language_id: current_language&.id
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
if @model_scope.respond_to?(:to_ary)
|
48
|
+
serializer_options[:each_serializer] = serializer
|
49
|
+
end
|
50
|
+
|
51
|
+
serializer.new(@model_scope, serializer_options)
|
52
|
+
end
|
53
|
+
|
54
|
+
def serialize
|
55
|
+
# NOTE: ActiveModelSerializers::Adapter#create is from active_model_serializers
|
56
|
+
ActiveModelSerializers::Adapter.create(
|
57
|
+
serializer_instance,
|
58
|
+
key_transform: key_transform,
|
59
|
+
include: included,
|
60
|
+
fields: fields,
|
61
|
+
meta: meta,
|
62
|
+
serialization_context: request
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module JSONAPIHelpers
|
6
|
+
module Serializers
|
7
|
+
module ModelError
|
8
|
+
KNOWN_ERROR_TYPES = Set.new(%i(
|
9
|
+
accepted
|
10
|
+
blank
|
11
|
+
confirmation
|
12
|
+
empty
|
13
|
+
equal_to
|
14
|
+
even
|
15
|
+
exclusion
|
16
|
+
greater_than
|
17
|
+
greater_than_or_equal_to
|
18
|
+
inclusion
|
19
|
+
invalid
|
20
|
+
less_than
|
21
|
+
less_than_or_equal_to
|
22
|
+
not_a_number
|
23
|
+
not_an_integer
|
24
|
+
odd
|
25
|
+
other_than
|
26
|
+
present
|
27
|
+
required
|
28
|
+
taken
|
29
|
+
too_long
|
30
|
+
too_short
|
31
|
+
wrong_length
|
32
|
+
)).freeze
|
33
|
+
|
34
|
+
def self.serialize(model, key_transform: JSONAPIHelpers.config.key_transform)
|
35
|
+
model.errors.details.flat_map do |field, errors|
|
36
|
+
errors.map do |error|
|
37
|
+
attribute_name = KeyTransform.call(field.to_s, key_transform: key_transform)
|
38
|
+
|
39
|
+
{
|
40
|
+
status: 422,
|
41
|
+
source: { pointer: "/data/attributes/#{attribute_name}" },
|
42
|
+
detail: error_message_for(model.errors, field, error),
|
43
|
+
meta: error_meta_for(error)
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.error_message_for(model_errors, field, error)
|
50
|
+
message = error.fetch(:error)
|
51
|
+
return message if message.is_a?(String) # expects it to already be translated
|
52
|
+
|
53
|
+
model_errors.generate_message(field, message, count: error[:count])
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.error_meta_for(error)
|
57
|
+
meta = {
|
58
|
+
type: error_type_for(error.fetch(:error))
|
59
|
+
}
|
60
|
+
meta[:count] = error[:count] if error[:count]
|
61
|
+
meta[:value] = error[:value] if error[:value]
|
62
|
+
meta
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.error_type_for(error_type)
|
66
|
+
return error_type if KNOWN_ERROR_TYPES.include?(error_type)
|
67
|
+
:invalid
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/hash/keys'
|
4
|
+
|
5
|
+
module JSONAPIHelpers
|
6
|
+
module Serializers
|
7
|
+
class Relationships
|
8
|
+
def initialize
|
9
|
+
@relationships = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(relation:, id:, type:)
|
13
|
+
@relationships[relation] = { id: id, type: type }
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_h
|
17
|
+
@relationships
|
18
|
+
end
|
19
|
+
|
20
|
+
# Rails is awkward and calls #to_json with a context argument
|
21
|
+
# NOTE: Rails only method Hash#to_json
|
22
|
+
def to_json(_context = nil)
|
23
|
+
to_h.to_json
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/string'
|
4
|
+
require 'active_support/core_ext/hash/keys'
|
5
|
+
|
6
|
+
# Slightly modified from https://github.com/rails-api/active_model_serializers/blob/a1826186e556b4aa6cbe2a2588df8b2186e06252/lib/active_model_serializers/key_transform.rb
|
7
|
+
module JSONAPIHelpers
|
8
|
+
module KeyTransform
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def call(object, key_transform: nil)
|
12
|
+
key_transform ||= JSONAPIHelpers.config.key_transform
|
13
|
+
public_send(key_transform, object)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Transforms values to UpperCamelCase or PascalCase.
|
17
|
+
#
|
18
|
+
# @example:
|
19
|
+
# "some_key" => "SomeKey",
|
20
|
+
def camel(value)
|
21
|
+
case value
|
22
|
+
when Hash then value.deep_transform_keys! { |key| camel(key) }
|
23
|
+
when Symbol then camel(value.to_s).to_sym
|
24
|
+
when String then StringSupport.camel(value)
|
25
|
+
else value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Transforms values to camelCase.
|
30
|
+
#
|
31
|
+
# @example:
|
32
|
+
# "some_key" => "someKey",
|
33
|
+
def camel_lower(value)
|
34
|
+
case value
|
35
|
+
when Hash then value.deep_transform_keys! { |key| camel_lower(key) }
|
36
|
+
when Symbol then camel_lower(value.to_s).to_sym
|
37
|
+
when String then StringSupport.camel_lower(value)
|
38
|
+
else value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Transforms values to dashed-case.
|
43
|
+
# This is the default case for the JsonApi adapter.
|
44
|
+
#
|
45
|
+
# @example:
|
46
|
+
# "some_key" => "some-key",
|
47
|
+
def dash(value)
|
48
|
+
case value
|
49
|
+
when Hash then value.deep_transform_keys! { |key| dash(key) }
|
50
|
+
when Symbol then dash(value.to_s).to_sym
|
51
|
+
when String then StringSupport.dash(value)
|
52
|
+
else value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Transforms values to underscore_case.
|
57
|
+
# This is the default case for deserialization in the JsonApi adapter.
|
58
|
+
#
|
59
|
+
# @example:
|
60
|
+
# "some-key" => "some_key",
|
61
|
+
def underscore(value)
|
62
|
+
case value
|
63
|
+
when Hash then value.deep_transform_keys! { |key| underscore(key) }
|
64
|
+
when Symbol then underscore(value.to_s).to_sym
|
65
|
+
when String then StringSupport.underscore(value)
|
66
|
+
else value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns the value unaltered
|
71
|
+
def unaltered(value)
|
72
|
+
value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JSONAPIHelpers
|
4
|
+
module StringSupport
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def camel(string)
|
8
|
+
string.underscore.camelize
|
9
|
+
end
|
10
|
+
|
11
|
+
def camel_lower(string)
|
12
|
+
string.underscore.camelize(:lower)
|
13
|
+
end
|
14
|
+
|
15
|
+
def dash(string)
|
16
|
+
string.underscore.dasherize
|
17
|
+
end
|
18
|
+
|
19
|
+
def underscore(string)
|
20
|
+
string.underscore
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonapi_helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacob Burenstam
|
@@ -116,11 +116,32 @@ executables: []
|
|
116
116
|
extensions: []
|
117
117
|
extra_rdoc_files: []
|
118
118
|
files:
|
119
|
+
- ".gitignore"
|
120
|
+
- ".rspec"
|
121
|
+
- ".travis.yml"
|
122
|
+
- Gemfile
|
119
123
|
- LICENSE.txt
|
120
|
-
- README.
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
121
126
|
- bin/console
|
122
127
|
- bin/setup
|
128
|
+
- jsonapi_helpers.gemspec
|
129
|
+
- lib/jsonapi_helpers.rb
|
123
130
|
- lib/jsonapi_helpers/action_dispatch_request_wrapper.rb
|
131
|
+
- lib/jsonapi_helpers/params/fields.rb
|
132
|
+
- lib/jsonapi_helpers/params/filter.rb
|
133
|
+
- lib/jsonapi_helpers/params/includes.rb
|
134
|
+
- lib/jsonapi_helpers/params/sort.rb
|
135
|
+
- lib/jsonapi_helpers/serializers/data.rb
|
136
|
+
- lib/jsonapi_helpers/serializers/datum.rb
|
137
|
+
- lib/jsonapi_helpers/serializers/deserializer.rb
|
138
|
+
- lib/jsonapi_helpers/serializers/error.rb
|
139
|
+
- lib/jsonapi_helpers/serializers/errors.rb
|
140
|
+
- lib/jsonapi_helpers/serializers/model.rb
|
141
|
+
- lib/jsonapi_helpers/serializers/model_error.rb
|
142
|
+
- lib/jsonapi_helpers/serializers/relationships.rb
|
143
|
+
- lib/jsonapi_helpers/support/key_transform.rb
|
144
|
+
- lib/jsonapi_helpers/support/string_support.rb
|
124
145
|
- lib/jsonapi_helpers/version.rb
|
125
146
|
homepage: https://github.com/buren/jsonapi_helpers
|
126
147
|
licenses:
|