fields-serializer 0.4.0 → 0.5.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/lib/fields/serializer/action_controller.rb +3 -4
- data/lib/fields/serializer/active_record.rb +33 -37
- data/lib/fields/serializer/fields_tree.rb +92 -0
- data/lib/fields/serializer/version.rb +1 -1
- data/lib/fields/serializer.rb +1 -1
- metadata +3 -3
- data/lib/fields/serializer/field_serializer.rb +0 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d97826f68957ac11395bfc95787ebc4562a49891
|
4
|
+
data.tar.gz: dba35d1851970293eb3fcf3ac8992cb8108bc801
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 429db7023534cb8168d610708cca7705a3ec3127da0d390d2472b989f0645071f63907c3c21fc12990bacd10bea1c0e29c7535f8e774e2f680c4dbb150594818
|
7
|
+
data.tar.gz: 2a2b8473e52a57245db3333d18603bd759c094917a484391476c47e49de1ca70424e1ec3d6e739d55a34c659dccbfbca181d8e9646fc53d84597378ffd694569
|
@@ -17,10 +17,9 @@ module Fields
|
|
17
17
|
fields = options.delete(:fields)
|
18
18
|
model_class = options.delete(:model_class)
|
19
19
|
if fields.present?
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
options.merge!(include: includes)
|
20
|
+
query = query.includes(*model_class.fields_to_includes(fields))
|
21
|
+
options.merge!(each_serializer: model_class.fields_serializer(fields))
|
22
|
+
options.delete(:include)
|
24
23
|
end
|
25
24
|
render options.merge!(json: query.to_a)
|
26
25
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_record'
|
2
|
+
require "active_model_serializers"
|
2
3
|
|
3
4
|
module Fields
|
4
5
|
module Serializer
|
@@ -13,57 +14,52 @@ module Fields
|
|
13
14
|
#
|
14
15
|
# BoilerPack.fields_to_includes("id,boiler.gas_safe_code") #=> ["boiler"]
|
15
16
|
#
|
16
|
-
def fields_to_includes(fields)
|
17
|
-
|
18
|
-
if attribute_structure.is_a?(Hash)
|
19
|
-
result.first.deep_merge!(attribute_structure) { |_, u, v| u == v ? u : [u, v] }
|
20
|
-
else
|
21
|
-
result << attribute_structure unless result.first.dig(attribute_structure) || result.include?(attribute_structure)
|
22
|
-
end
|
23
|
-
result
|
24
|
-
end.map(&:presence).compact
|
17
|
+
def fields_to_includes(*fields)
|
18
|
+
fields_to_tree(fields).to_includes
|
25
19
|
end
|
26
20
|
|
27
|
-
|
28
|
-
|
29
|
-
#
|
30
|
-
# Example:
|
31
|
-
#
|
32
|
-
# BoilerPack.fields_to_includes("id,boiler.gas_safe_code") #=> ["boiler"]
|
33
|
-
#
|
34
|
-
def fields_to_include(fields, root: nil)
|
35
|
-
Array(fields).map do |field|
|
36
|
-
if field.kind_of?(Hash) || field.kind_of?(Array)
|
37
|
-
field.map { |k, v| fields_to_include(v, root: composite_field(root, k)) }
|
38
|
-
else
|
39
|
-
composite_field(root, field)
|
40
|
-
end
|
41
|
-
end.flatten
|
21
|
+
def fields_serializer(*fields)
|
22
|
+
create_serializer_class(fields_to_tree(fields).notation)
|
42
23
|
end
|
43
24
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
25
|
+
def create_serializer_class(fields)
|
26
|
+
Class.new(ActiveModel::Serializer) do
|
27
|
+
Array(fields).each do |field|
|
28
|
+
if field.kind_of?(Hash)
|
29
|
+
nested_association(field)
|
30
|
+
else
|
31
|
+
attribute field.to_sym unless association?(field)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
49
35
|
end
|
50
36
|
|
51
37
|
private
|
52
38
|
|
53
|
-
def
|
54
|
-
|
39
|
+
def fields_to_tree(*fields)
|
40
|
+
array_fields(fields.flatten).inject(FieldsTree.new(self), &:merge!)
|
55
41
|
end
|
56
42
|
|
57
|
-
|
58
|
-
|
43
|
+
# Calls:
|
44
|
+
# has_one :user, serializer: new_serializer_class_for_user_fields
|
45
|
+
# or
|
46
|
+
# belongs_to :user, serializer: new_serializer_class_for_user_fields
|
47
|
+
# or
|
48
|
+
# has_many :users, serializer: new_serializer_class_for_user_fields
|
49
|
+
#
|
50
|
+
def nested_association(fields)
|
51
|
+
fields.each do |association_name, nested_fields|
|
52
|
+
reflection = reflections[association_name]
|
53
|
+
send(reflection.macro, association_name.to_sym, serializer: reflection.klass.create_serializer_class(nested_fields))
|
54
|
+
end
|
59
55
|
end
|
60
56
|
|
61
|
-
def
|
62
|
-
|
57
|
+
def array_fields(fields)
|
58
|
+
Array(fields).map { |str| str.to_s.split(",").map(&:strip) }.flatten.sort
|
63
59
|
end
|
64
60
|
|
65
|
-
def
|
66
|
-
|
61
|
+
def association?(key)
|
62
|
+
reflections.keys.include?(key)
|
67
63
|
end
|
68
64
|
end
|
69
65
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require "active_model_serializers"
|
3
|
+
|
4
|
+
module Fields
|
5
|
+
module Serializer
|
6
|
+
|
7
|
+
class FieldsTree
|
8
|
+
attr_reader :klass, :fields, :associations
|
9
|
+
|
10
|
+
def initialize(klass)
|
11
|
+
@klass = klass
|
12
|
+
@fields = []
|
13
|
+
@associations = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def presence
|
17
|
+
self if fields.present? || associations.present?
|
18
|
+
end
|
19
|
+
|
20
|
+
def merge!(join_field)
|
21
|
+
return self unless join_field.present?
|
22
|
+
parent, rest = join_field.to_s.split(".", 2)
|
23
|
+
if rest.blank?
|
24
|
+
fields << parent if !(existing_field?(parent) || association?(parent))
|
25
|
+
else
|
26
|
+
existing_association?(parent) ? associations[parent].merge!(rest) : add_association!(parent, rest)
|
27
|
+
end
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def notation
|
32
|
+
if fields.present?
|
33
|
+
if associations.present?
|
34
|
+
fields.dup << associations_to_notation
|
35
|
+
else
|
36
|
+
fields.one? ? fields.first.dup : fields.dup
|
37
|
+
end
|
38
|
+
else
|
39
|
+
associations_to_notation.presence
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_includes
|
44
|
+
to_includes = associations.inject([]) do |result, (k, v)|
|
45
|
+
v_includes = v.to_includes
|
46
|
+
if v_includes.present?
|
47
|
+
new_has_entry = { k => v_includes }
|
48
|
+
hash = result.find { |e| e.is_a?(Hash) }
|
49
|
+
hash ? hash.merge!(new_has_entry) : (result << new_has_entry)
|
50
|
+
result
|
51
|
+
else
|
52
|
+
result << k
|
53
|
+
end
|
54
|
+
end.presence
|
55
|
+
Array(to_includes).one? ? to_includes.first : to_includes
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
notation.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def add_association!(parent, rest)
|
65
|
+
if association?(parent)
|
66
|
+
nested_class = klass.reflections[parent].klass
|
67
|
+
nested_fields_tree = FieldsTree.new(nested_class).merge!(rest).presence
|
68
|
+
new_association = { parent => nested_fields_tree } if nested_fields_tree
|
69
|
+
associations.merge!(new_association) if new_association
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def associations_to_notation
|
74
|
+
associations.inject({}) do |result, (k, v)|
|
75
|
+
result.merge!(k => v.notation)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def existing_association?(value)
|
80
|
+
!!associations[value]
|
81
|
+
end
|
82
|
+
|
83
|
+
def existing_field?(value)
|
84
|
+
fields.include?(value)
|
85
|
+
end
|
86
|
+
|
87
|
+
def association?(value)
|
88
|
+
klass.reflections.keys.include?(value)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/fields/serializer.rb
CHANGED
@@ -4,7 +4,7 @@ require 'active_support/concern'
|
|
4
4
|
require "fields/serializer/version"
|
5
5
|
require "fields/serializer/active_record"
|
6
6
|
require "fields/serializer/action_controller"
|
7
|
-
require "fields/serializer/
|
7
|
+
require "fields/serializer/fields_tree"
|
8
8
|
|
9
9
|
module Fields
|
10
10
|
module Serializer
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fields-serializer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stuart Chinery
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-12-
|
13
|
+
date: 2017-12-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -145,7 +145,7 @@ files:
|
|
145
145
|
- lib/fields/serializer.rb
|
146
146
|
- lib/fields/serializer/action_controller.rb
|
147
147
|
- lib/fields/serializer/active_record.rb
|
148
|
-
- lib/fields/serializer/
|
148
|
+
- lib/fields/serializer/fields_tree.rb
|
149
149
|
- lib/fields/serializer/version.rb
|
150
150
|
homepage: https://github.com/ltello/fields-serializer
|
151
151
|
licenses:
|
@@ -1,56 +0,0 @@
|
|
1
|
-
require "active_model_serializers"
|
2
|
-
|
3
|
-
# This is a generic serializer intended to return a subset of a model's attributes.
|
4
|
-
# It can be used with any model but does not currently support associations.
|
5
|
-
#
|
6
|
-
# Example usage:
|
7
|
-
# render json: @region, serializer: FieldSerializer, fields: [:id, :title]
|
8
|
-
#
|
9
|
-
# > { "id": "5f19582d-ee28-4e89-9e3a-edc42a8b59e5", "title": "London" }
|
10
|
-
#
|
11
|
-
class FieldSerializer < ActiveModel::Serializer
|
12
|
-
def attributes(*args)
|
13
|
-
fields = Array(args.first).map { |str| str.to_s.split(",").map(&:strip) }.flatten
|
14
|
-
adding_id do
|
15
|
-
merging_attributes do
|
16
|
-
fields.map { |field| create_attribute_structure(field.split("."), object) }
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def adding_id(&block)
|
24
|
-
block.call.merge(id: object.id)
|
25
|
-
end
|
26
|
-
|
27
|
-
def create_attribute_structure(attribute_stack, model)
|
28
|
-
return model unless model.present?
|
29
|
-
if model.kind_of?(ActiveRecord::Relation)
|
30
|
-
collection_attribute_structure(model, attribute_stack)
|
31
|
-
else
|
32
|
-
parent = attribute_stack.first
|
33
|
-
if attribute_stack.count > 1
|
34
|
-
attribute_structure(model, attribute_stack[1..-1], parent)
|
35
|
-
else
|
36
|
-
value_structure(model, parent)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def attribute_structure(model, attribute_stack, parent)
|
42
|
-
{ parent => create_attribute_structure(attribute_stack, model.send(parent)) }
|
43
|
-
end
|
44
|
-
|
45
|
-
def collection_attribute_structure(models, attribute_stack)
|
46
|
-
models.map { |model| create_attribute_structure(attribute_stack, model) }.compact
|
47
|
-
end
|
48
|
-
|
49
|
-
def merging_attributes(&block)
|
50
|
-
block.call.inject(:deep_merge!)
|
51
|
-
end
|
52
|
-
|
53
|
-
def value_structure(model, attribute_name)
|
54
|
-
{ attribute_name => model.send(attribute_name) }
|
55
|
-
end
|
56
|
-
end
|