simple_json_api 0.0.3 → 0.0.4
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/Gemfile +14 -2
- data/README.md +1 -1
- data/lib/generators/simple_json_api/resource/USAGE +8 -0
- data/lib/generators/simple_json_api/resource/resource_generator.rb +73 -0
- data/lib/generators/simple_json_api/resource/templates/controller_template.rb.erb +34 -0
- data/lib/generators/simple_json_api/resource/templates/serializer_template.rb.erb +14 -0
- data/lib/simple_json_api/api_node.rb +68 -0
- data/lib/simple_json_api/array_serializer.rb +15 -1
- data/lib/simple_json_api/association.rb +16 -0
- data/lib/simple_json_api/attribute.rb +9 -0
- data/lib/simple_json_api/builder.rb +35 -0
- data/lib/simple_json_api/dsl.rb +35 -5
- data/lib/simple_json_api/field_list.rb +2 -7
- data/lib/simple_json_api/helper.rb +5 -0
- data/lib/simple_json_api/include_list.rb +12 -7
- data/lib/simple_json_api/json_api_wrapper.rb +46 -0
- data/lib/simple_json_api/member/data.rb +14 -0
- data/lib/simple_json_api/member/included.rb +38 -0
- data/lib/simple_json_api/member/links.rb +9 -0
- data/lib/simple_json_api/member/meta.rb +9 -0
- data/lib/simple_json_api/refinements/active_record.rb +23 -0
- data/lib/simple_json_api/refinements/array.rb +13 -0
- data/lib/simple_json_api/refinements/symbol.rb +17 -0
- data/lib/simple_json_api/resource.rb +23 -0
- data/lib/simple_json_api/resource_serializer.rb +25 -24
- data/lib/simple_json_api/serializer.rb +39 -2
- data/lib/simple_json_api/serializer_factory.rb +22 -0
- data/lib/simple_json_api/version.rb +1 -1
- data/lib/simple_json_api.rb +7 -29
- data/simple_json_api.gemspec +2 -7
- data/test/generators/simple_json_api/resource_generator_test.rb +31 -0
- data/test/integration/render_basic_test.rb +10 -7
- data/test/integration/render_fields_test.rb +35 -16
- data/test/integration/render_include_test.rb +66 -63
- data/test/integration/render_nested_include_test.rb +38 -83
- data/test/integration/serializers_test.rb +1 -1
- data/test/setup/data.rb +7 -3
- data/test/setup/serializers.rb +2 -0
- data/test/test_helper.rb +3 -9
- data/test/unit/field_list_test.rb +0 -10
- data/test/unit/include_list_test.rb +35 -5
- data/test/unit/symbol_refinement_test.rb +16 -0
- metadata +25 -89
- data/lib/simple_json_api/active_record_refinements.rb +0 -21
- data/lib/simple_json_api/array_refinements.rb +0 -14
- data/lib/simple_json_api/json_api_builder.rb +0 -84
@@ -2,19 +2,24 @@
|
|
2
2
|
module SimpleJsonApi
|
3
3
|
# List of Included associations for a resource
|
4
4
|
class IncludeList
|
5
|
+
attr_reader :include_hash
|
6
|
+
|
5
7
|
def initialize(include)
|
6
8
|
@include = include
|
7
|
-
|
9
|
+
# autovivificious hash
|
10
|
+
@include_hash = Hash.new do |hash, key|
|
11
|
+
hash[key] = Hash.new(&hash.default_proc)
|
12
|
+
end
|
8
13
|
end
|
9
14
|
|
10
15
|
def parse
|
11
|
-
@
|
16
|
+
@include.split(',').each do |a|
|
17
|
+
inc = a.split('.').inject(@include_hash) do |hash, key|
|
18
|
+
hash[key.pluralize.to_sym]
|
19
|
+
end
|
20
|
+
inc[:include] = true
|
21
|
+
end if @include
|
12
22
|
self
|
13
23
|
end
|
14
|
-
|
15
|
-
def include?(resource, parent = [])
|
16
|
-
path = [parent, resource].flatten.compact.join('.')
|
17
|
-
@include_list.include?(path)
|
18
|
-
end
|
19
24
|
end
|
20
25
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'simple_json_api/member/data'
|
2
|
+
require 'simple_json_api/member/included'
|
3
|
+
require 'simple_json_api/member/links'
|
4
|
+
require 'simple_json_api/member/meta'
|
5
|
+
|
6
|
+
module SimpleJsonApi
|
7
|
+
# JSONAPI Wrapper
|
8
|
+
class JsonApiWrapper
|
9
|
+
def initialize(root_node)
|
10
|
+
@root_node = root_node
|
11
|
+
@result = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def as_json(_options = nil)
|
15
|
+
add_members
|
16
|
+
@result.delete_if { |_, content| content.blank? }
|
17
|
+
@result
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def add_members
|
23
|
+
links
|
24
|
+
meta
|
25
|
+
data
|
26
|
+
included
|
27
|
+
end
|
28
|
+
|
29
|
+
def links
|
30
|
+
@result[:links] ||= Member::Links.new.content
|
31
|
+
end
|
32
|
+
|
33
|
+
def meta
|
34
|
+
@result[:meta] ||= Member::Meta.new.content
|
35
|
+
end
|
36
|
+
|
37
|
+
def data
|
38
|
+
@result[:data] ||= Member::Data.new(@root_node).content
|
39
|
+
end
|
40
|
+
|
41
|
+
def included
|
42
|
+
@result[:included] ||=
|
43
|
+
Member::Included.new(@root_node, @result[:data]).content
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module SimpleJsonApi
|
2
|
+
module Member
|
3
|
+
# JSONAPI Included top-level member
|
4
|
+
class Included
|
5
|
+
def initialize(root_node, data)
|
6
|
+
@root_node = root_node
|
7
|
+
@data = data
|
8
|
+
@included = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def content
|
12
|
+
visit(@root_node)
|
13
|
+
@included
|
14
|
+
end
|
15
|
+
|
16
|
+
def visit(node)
|
17
|
+
node.associations.each do |association|
|
18
|
+
process(association) if included?(association)
|
19
|
+
visit(association)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def process(association)
|
24
|
+
Array[association.serialize].flatten.each do |hash|
|
25
|
+
@included << hash unless already_included? hash
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def included?(association)
|
30
|
+
association.assoc_list[:include].present?
|
31
|
+
end
|
32
|
+
|
33
|
+
def already_included?(resource)
|
34
|
+
@included.include?(resource) || Array(@data).include?(resource)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
# SimpleJsonApi
|
4
|
+
module SimpleJsonApi
|
5
|
+
module Refinements
|
6
|
+
# Refinements on ActiveRecord
|
7
|
+
module ActiveRecord
|
8
|
+
refine ::ActiveRecord::Base do
|
9
|
+
def typed_json_id
|
10
|
+
[self.class.to_s.downcase.pluralize, json_id]
|
11
|
+
end
|
12
|
+
|
13
|
+
def json_id
|
14
|
+
send(json_pk).to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def json_pk
|
18
|
+
self.class.primary_key.to_sym
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# SimpleJsonApi
|
2
|
+
module SimpleJsonApi
|
3
|
+
module Refinements
|
4
|
+
# Refinements on Hash
|
5
|
+
module Symbol
|
6
|
+
refine ::Symbol do
|
7
|
+
def pluralize
|
8
|
+
to_s.pluralize.to_sym
|
9
|
+
end
|
10
|
+
|
11
|
+
def singularize
|
12
|
+
to_s.singularize.to_sym
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SimpleJsonApi
|
2
|
+
# The representation of a Resource
|
3
|
+
class Resource
|
4
|
+
extend Forwardable
|
5
|
+
def_delegators :@content, :[], :as_json
|
6
|
+
|
7
|
+
def initialize(content)
|
8
|
+
@content = content
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
(@content[:type] &&
|
13
|
+
(@content[:type] == other[:type])) &&
|
14
|
+
(@content[:id] &&
|
15
|
+
(@content[:id] == other[:id]))
|
16
|
+
end
|
17
|
+
# alias_method :eql?, :==
|
18
|
+
|
19
|
+
# def hash
|
20
|
+
# [@content[:id], @content[:type], Resource].hash
|
21
|
+
# end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,27 +1,39 @@
|
|
1
|
+
require 'simple_json_api/refinements/active_record'
|
2
|
+
require 'simple_json_api/refinements/symbol'
|
3
|
+
|
1
4
|
# SimpleJsonApi
|
2
5
|
module SimpleJsonApi
|
3
6
|
# The Serializer will serialize a model
|
4
7
|
class ResourceSerializer < Serializer
|
5
|
-
using
|
8
|
+
using Refinements::ActiveRecord
|
9
|
+
using Refinements::Symbol
|
6
10
|
|
7
11
|
def _root_name
|
8
12
|
self.class._root_name
|
9
13
|
end
|
10
14
|
|
15
|
+
def type
|
16
|
+
_root_name
|
17
|
+
end
|
18
|
+
|
19
|
+
def id
|
20
|
+
_object.try(:id) || _object.try(:guid)
|
21
|
+
end
|
22
|
+
|
11
23
|
def _fields
|
12
|
-
@_fields ||=
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
24
|
+
@_fields ||= _get_fields
|
25
|
+
end
|
26
|
+
|
27
|
+
# If default_fields is not specified, use all_fields
|
28
|
+
def _get_fields
|
29
|
+
builder_fields
|
17
30
|
end
|
18
31
|
|
19
32
|
def serialize
|
20
33
|
hash = {}
|
21
34
|
attribute_values(hash)
|
22
35
|
link_values(hash[:links] = {})
|
23
|
-
|
24
|
-
hash
|
36
|
+
Resource.new(hash)
|
25
37
|
end
|
26
38
|
|
27
39
|
def attribute_values(hash)
|
@@ -38,31 +50,20 @@ module SimpleJsonApi
|
|
38
50
|
end
|
39
51
|
|
40
52
|
def link(association)
|
41
|
-
resource = send(association.name)
|
42
53
|
if association.type == :has_many
|
43
|
-
|
54
|
+
includes = association.polymorphic ? [] : Serializer.includes(association)
|
55
|
+
resource = send(association.name, includes)
|
56
|
+
resource.map do |obj|
|
44
57
|
association[:polymorphic] ? obj.typed_json_id : obj.json_id
|
45
58
|
end
|
46
59
|
else
|
47
|
-
resource.
|
60
|
+
resource = send(association.name)
|
61
|
+
resource.json_id if resource
|
48
62
|
end
|
49
63
|
end
|
50
64
|
|
51
65
|
def _associations
|
52
66
|
self.class._associations
|
53
67
|
end
|
54
|
-
|
55
|
-
def _association_values
|
56
|
-
_associations.each do |association|
|
57
|
-
name = association[:name]
|
58
|
-
obj = send(name)
|
59
|
-
_builder.add_linked_elem(
|
60
|
-
name,
|
61
|
-
obj,
|
62
|
-
association,
|
63
|
-
@_base
|
64
|
-
)
|
65
|
-
end
|
66
|
-
end
|
67
68
|
end
|
68
69
|
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'simple_json_api/dsl'
|
2
|
+
# require 'simple_json_api/refinements/array'
|
3
|
+
|
1
4
|
# SimpleJsonApi
|
2
5
|
module SimpleJsonApi
|
3
6
|
# The Serializer will serialize a model
|
@@ -16,6 +19,34 @@ module SimpleJsonApi
|
|
16
19
|
@_base = base
|
17
20
|
end
|
18
21
|
|
22
|
+
def associated_object(association_name)
|
23
|
+
send(association_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def default_fields
|
29
|
+
self.class._default_fields
|
30
|
+
end
|
31
|
+
|
32
|
+
def all_fields
|
33
|
+
self.class.default_attributes.split(',')
|
34
|
+
end
|
35
|
+
|
36
|
+
def required_fields
|
37
|
+
[:type, :id]
|
38
|
+
end
|
39
|
+
|
40
|
+
def builder_fields
|
41
|
+
bf = _builder.fields_for(_root_name).presence
|
42
|
+
fields = if bf.present?
|
43
|
+
(required_fields + Array(bf)).uniq
|
44
|
+
else
|
45
|
+
default_fields ? default_fields & all_fields : all_fields
|
46
|
+
end
|
47
|
+
(required_fields + Array(fields)).uniq.map(&:to_sym)
|
48
|
+
end
|
49
|
+
|
19
50
|
class << self
|
20
51
|
attr_reader :registered_serializers
|
21
52
|
|
@@ -26,6 +57,7 @@ module SimpleJsonApi
|
|
26
57
|
end
|
27
58
|
|
28
59
|
def for(model, association)
|
60
|
+
return association.serializer if association.serializer.present?
|
29
61
|
if association[:polymorphic]
|
30
62
|
for_polymorphic(model)
|
31
63
|
else
|
@@ -33,19 +65,24 @@ module SimpleJsonApi
|
|
33
65
|
end
|
34
66
|
end
|
35
67
|
|
68
|
+
def includes(association)
|
69
|
+
serializer = Serializer.for_regular(association)
|
70
|
+
serializer._associations.reject(&:polymorphic).map { |a| a[:name] } if serializer
|
71
|
+
end
|
72
|
+
|
36
73
|
def for_regular(association)
|
37
74
|
resource = association[:name].to_s.pluralize.to_sym
|
38
75
|
serializer = @registered_serializers.find do |entry|
|
39
76
|
entry[:resource] == resource
|
40
77
|
end
|
41
|
-
serializer[:serializer]
|
78
|
+
serializer[:serializer] if serializer
|
42
79
|
end
|
43
80
|
|
44
81
|
def for_polymorphic(model)
|
45
82
|
serializer = @registered_serializers.find do |entry|
|
46
83
|
entry[:model] == model.class
|
47
84
|
end
|
48
|
-
serializer[:serializer]
|
85
|
+
serializer[:serializer] if serializer
|
49
86
|
end
|
50
87
|
end
|
51
88
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'simple_json_api/serializer'
|
2
|
+
require 'simple_json_api/array_serializer'
|
3
|
+
require 'simple_json_api/resource_serializer'
|
4
|
+
|
5
|
+
# SimpleJsonApi
|
6
|
+
module SimpleJsonApi
|
7
|
+
# The SerializerFactory will return the serializer for an object
|
8
|
+
class SerializerFactory
|
9
|
+
def self.create(object, serializer, builder)
|
10
|
+
if use_array_serializer?(object)
|
11
|
+
ArraySerializer.new(object, builder, serializer)
|
12
|
+
else
|
13
|
+
serializer.new(object, builder)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.use_array_serializer?(object)
|
18
|
+
object.is_a?(Array) ||
|
19
|
+
object.is_a?(ActiveRecord::Associations::CollectionProxy)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/simple_json_api.rb
CHANGED
@@ -1,38 +1,16 @@
|
|
1
1
|
require 'simple_json_api/version'
|
2
2
|
|
3
|
-
require 'simple_json_api/
|
4
|
-
require 'simple_json_api/
|
5
|
-
|
6
|
-
|
7
|
-
require 'simple_json_api/dsl'
|
8
|
-
require 'simple_json_api/field_list'
|
9
|
-
require 'simple_json_api/include_list'
|
3
|
+
require 'simple_json_api/json_api_wrapper'
|
4
|
+
require 'simple_json_api/builder'
|
5
|
+
require 'simple_json_api/resource'
|
6
|
+
require 'simple_json_api/helper'
|
10
7
|
|
11
|
-
require 'simple_json_api/
|
12
|
-
require 'simple_json_api/array_serializer'
|
13
|
-
require 'simple_json_api/resource_serializer'
|
14
|
-
|
15
|
-
require 'simple_json_api/json_api_builder'
|
8
|
+
# require 'simple_json_api/helper'
|
16
9
|
|
17
10
|
# SimpleJsonApi
|
18
11
|
module SimpleJsonApi
|
19
|
-
# Wrapper for a linked association
|
20
|
-
Association = Struct.new(:name, :type, :serializer, :polymorphic, :key) do
|
21
|
-
def key
|
22
|
-
name_s = name.to_s
|
23
|
-
(type == :has_many) ? name_s.pluralize.to_sym : name_s.singularize.to_sym
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# Attribute
|
28
|
-
Attribute = Struct.new(:name, :key) do
|
29
|
-
def key
|
30
|
-
self[:key] || self[:name]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
12
|
# Main hook to generate json
|
35
|
-
def self.render(model:, serializer:,
|
36
|
-
|
13
|
+
def self.render(model:, serializer:, fields: nil, include: nil, wrapper: JsonApiWrapper)
|
14
|
+
Builder.new(model, wrapper, serializer, fields, include).to_json
|
37
15
|
end
|
38
16
|
end
|