fields-serializer 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|