jsonapi_helpers 0.1.1 → 0.2.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/.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:
|