simple_ams 0.2.5 → 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +28 -0
- data/.rubocop.yml +56 -0
- data/CHANGELOG.md +22 -0
- data/Gemfile +2 -2
- data/README.md +663 -116
- data/Rakefile +3 -3
- data/bin/console +3 -3
- data/lib/simple_ams.rb +34 -33
- data/lib/simple_ams/adapters/ams.rb +26 -32
- data/lib/simple_ams/adapters/jsonapi.rb +46 -65
- data/lib/simple_ams/document.rb +38 -28
- data/lib/simple_ams/document/fields.rb +36 -37
- data/lib/simple_ams/document/forms.rb +7 -9
- data/lib/simple_ams/document/generics.rb +35 -37
- data/lib/simple_ams/document/links.rb +7 -9
- data/lib/simple_ams/document/metas.rb +7 -11
- data/lib/simple_ams/document/primary_id.rb +14 -17
- data/lib/simple_ams/document/relations.rb +99 -109
- data/lib/simple_ams/dsl.rb +73 -71
- data/lib/simple_ams/methy.rb +2 -2
- data/lib/simple_ams/options.rb +268 -266
- data/lib/simple_ams/options/adapter.rb +2 -2
- data/lib/simple_ams/options/concerns/filterable.rb +29 -34
- data/lib/simple_ams/options/concerns/mod.rb +4 -0
- data/lib/simple_ams/options/concerns/name_value_hash.rb +25 -26
- data/lib/simple_ams/options/concerns/tracked_properties.rb +15 -17
- data/lib/simple_ams/options/concerns/value_hash.rb +25 -26
- data/lib/simple_ams/options/fields.rb +1 -1
- data/lib/simple_ams/options/forms.rb +1 -2
- data/lib/simple_ams/options/generics.rb +2 -4
- data/lib/simple_ams/options/includes.rb +1 -1
- data/lib/simple_ams/options/links.rb +1 -1
- data/lib/simple_ams/options/metas.rb +1 -1
- data/lib/simple_ams/options/primary_id.rb +1 -1
- data/lib/simple_ams/options/relations.rb +9 -7
- data/lib/simple_ams/options/type.rb +1 -2
- data/lib/simple_ams/renderer.rb +43 -41
- data/lib/simple_ams/version.rb +1 -1
- data/simple_ams.gemspec +17 -16
- metadata +38 -21
- data/.travis.yml +0 -15
data/lib/simple_ams/document.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'simple_ams'
|
2
2
|
|
3
3
|
class SimpleAMS::Document
|
4
4
|
attr_reader :options, :embedded_options, :serializer, :resource
|
@@ -17,12 +17,14 @@ class SimpleAMS::Document
|
|
17
17
|
def fields
|
18
18
|
return @fields if defined?(@fields)
|
19
19
|
return @fields = [] if options.fields.empty?
|
20
|
-
|
20
|
+
|
21
|
+
@fields ||= self.class::Fields.new(options)
|
21
22
|
end
|
22
23
|
|
23
24
|
def relations
|
24
25
|
return @relations if defined?(@relations)
|
25
|
-
|
26
|
+
|
27
|
+
@relations ||= self.class::Relations.new(
|
26
28
|
options, options.relations
|
27
29
|
)
|
28
30
|
end
|
@@ -42,30 +44,36 @@ class SimpleAMS::Document
|
|
42
44
|
def links
|
43
45
|
return @links if defined?(@links)
|
44
46
|
return @links = {} if options.links.empty?
|
45
|
-
|
47
|
+
|
48
|
+
@links ||= self.class::Links.new(options)
|
46
49
|
end
|
47
50
|
|
48
51
|
def metas
|
49
52
|
return @metas if defined?(@metas)
|
50
53
|
return @metas = {} if options.metas.empty?
|
51
|
-
|
54
|
+
|
55
|
+
@metas ||= self.class::Metas.new(options)
|
52
56
|
end
|
53
57
|
|
54
58
|
def forms
|
55
59
|
return @forms if defined?(@forms)
|
56
60
|
return @forms = {} if options.forms.empty?
|
57
|
-
|
61
|
+
|
62
|
+
@forms ||= self.class::Forms.new(options)
|
58
63
|
end
|
59
64
|
|
60
65
|
def generics
|
61
66
|
return @generics if defined?(@generics)
|
62
67
|
return @generics = {} if options.generics.empty?
|
63
|
-
|
68
|
+
|
69
|
+
@generics ||= self.class::Generics.new(options)
|
64
70
|
end
|
65
71
|
|
72
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
66
73
|
def folder?
|
67
|
-
@is_folder ||=
|
74
|
+
@is_folder ||= is_a?(self.class::Folder)
|
68
75
|
end
|
76
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
69
77
|
|
70
78
|
def document?
|
71
79
|
!folder?
|
@@ -91,7 +99,7 @@ class SimpleAMS::Document
|
|
91
99
|
@resource = options.resource
|
92
100
|
end
|
93
101
|
|
94
|
-
def each
|
102
|
+
def each
|
95
103
|
return enum_for(:each) unless block_given?
|
96
104
|
|
97
105
|
members.each do |resource|
|
@@ -101,7 +109,7 @@ class SimpleAMS::Document
|
|
101
109
|
self
|
102
110
|
end
|
103
111
|
|
104
|
-
#do we really need this method ?
|
112
|
+
# do we really need this method ?
|
105
113
|
def documents
|
106
114
|
each.map
|
107
115
|
end
|
@@ -111,26 +119,28 @@ class SimpleAMS::Document
|
|
111
119
|
end
|
112
120
|
|
113
121
|
private
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
})
|
124
|
-
|
125
|
-
|
126
|
-
|
122
|
+
|
123
|
+
attr_reader :_options
|
124
|
+
|
125
|
+
def options_for(resource)
|
126
|
+
if resource_options.serializer_class.respond_to?(:call)
|
127
|
+
SimpleAMS::Options.new(
|
128
|
+
resource,
|
129
|
+
injected_options: resource_options.injected_options.merge({
|
130
|
+
serializer: serializer_for(resource)
|
131
|
+
}),
|
132
|
+
allowed_options: serializer_for(resource).options
|
133
|
+
)
|
134
|
+
else
|
135
|
+
resource_options.with_resource(resource)
|
127
136
|
end
|
137
|
+
end
|
128
138
|
|
129
|
-
|
130
|
-
|
131
|
-
|
139
|
+
def serializer_for(resource)
|
140
|
+
serializer = resource_options.serializer_class
|
141
|
+
serializer = serializer.call(resource) if serializer.respond_to?(:call)
|
132
142
|
|
133
|
-
|
134
|
-
|
143
|
+
serializer
|
144
|
+
end
|
135
145
|
end
|
136
146
|
end
|
@@ -1,51 +1,50 @@
|
|
1
|
-
require
|
1
|
+
require 'simple_ams'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
include Enumerable
|
3
|
+
class SimpleAMS::Document::Fields
|
4
|
+
include Enumerable
|
6
5
|
|
7
|
-
|
6
|
+
Field = Struct.new(:key, :value)
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def [](key)
|
15
|
-
found = members.find{|field| field == key}
|
16
|
-
return nil unless found
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
@members = options.fields # [:field1, :field2]
|
11
|
+
end
|
17
12
|
|
18
|
-
|
19
|
-
|
13
|
+
def [](key)
|
14
|
+
found = members.find { |field| field == key }
|
15
|
+
return nil unless found
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
return enum_for(:each) unless block_given?
|
17
|
+
value_of(found)
|
18
|
+
end
|
24
19
|
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
# TODO: Can we make this faster?
|
21
|
+
def each
|
22
|
+
return enum_for(:each) unless block_given?
|
28
23
|
|
29
|
-
|
24
|
+
members.each do |key|
|
25
|
+
yield value_of(key)
|
30
26
|
end
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
end
|
28
|
+
self
|
29
|
+
end
|
35
30
|
|
36
|
-
|
37
|
-
|
38
|
-
|
31
|
+
def any?
|
32
|
+
members.any?
|
33
|
+
end
|
34
|
+
|
35
|
+
def empty?
|
36
|
+
members.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
39
40
|
|
40
|
-
|
41
|
-
attr_reader :members, :options
|
41
|
+
attr_reader :members, :options
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
43
|
+
def value_of(key)
|
44
|
+
if options.serializer.respond_to?(key)
|
45
|
+
Field.new(key, options.serializer.send(key))
|
46
|
+
else
|
47
|
+
Field.new(key, options.resource.send(key))
|
48
|
+
end
|
50
49
|
end
|
51
50
|
end
|
@@ -1,13 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require 'simple_ams'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
3
|
+
class SimpleAMS::Document::Forms < SimpleAMS::Document::Generics
|
4
|
+
def initialize(options)
|
5
|
+
@options = options
|
6
|
+
@members = options.forms
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
end
|
9
|
+
class Form < SimpleAMS::Document::Generics::Generic
|
12
10
|
end
|
13
11
|
end
|
@@ -1,51 +1,49 @@
|
|
1
|
-
require
|
1
|
+
require 'simple_ams'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
include Enumerable
|
3
|
+
class SimpleAMS::Document::Generics
|
4
|
+
include Enumerable
|
6
5
|
|
7
|
-
|
6
|
+
Generic = Struct.new(:name, :value, :options)
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def [](key)
|
15
|
-
found = members.find{|generic| generic.name == key}
|
16
|
-
return nil unless found
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
@members = options.generics
|
11
|
+
end
|
17
12
|
|
18
|
-
|
19
|
-
|
13
|
+
def [](key)
|
14
|
+
found = members.find { |generic| generic.name == key }
|
15
|
+
return nil unless found
|
20
16
|
|
21
|
-
|
22
|
-
|
17
|
+
with_decorator(found)
|
18
|
+
end
|
23
19
|
|
24
|
-
|
25
|
-
|
26
|
-
}
|
20
|
+
def each
|
21
|
+
return enum_for(:each) unless block_given?
|
27
22
|
|
28
|
-
|
23
|
+
members.each do |member|
|
24
|
+
yield with_decorator(member)
|
29
25
|
end
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
end
|
27
|
+
self
|
28
|
+
end
|
34
29
|
|
35
|
-
|
36
|
-
|
37
|
-
|
30
|
+
def any?
|
31
|
+
members.any?
|
32
|
+
end
|
33
|
+
|
34
|
+
def empty?
|
35
|
+
members.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
38
39
|
|
39
|
-
|
40
|
-
attr_reader :members, :options
|
40
|
+
attr_reader :members, :options
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
42
|
+
def with_decorator(generic)
|
43
|
+
Generic.new(
|
44
|
+
generic.name,
|
45
|
+
generic.respond_to?(:call) ? generic.value.call : generic.value,
|
46
|
+
generic.options
|
47
|
+
)
|
49
48
|
end
|
50
49
|
end
|
51
|
-
|
@@ -1,13 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require 'simple_ams'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
3
|
+
class SimpleAMS::Document::Links < SimpleAMS::Document::Generics
|
4
|
+
def initialize(options)
|
5
|
+
@options = options
|
6
|
+
@members = options.links
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
end
|
9
|
+
class Generic < SimpleAMS::Document::Generics::Generic
|
12
10
|
end
|
13
11
|
end
|
@@ -1,15 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require 'simple_ams'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
3
|
+
class SimpleAMS::Document::Metas < SimpleAMS::Document::Generics
|
4
|
+
def initialize(options)
|
5
|
+
@options = options
|
6
|
+
@members = options.metas
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
end
|
9
|
+
class Meta < SimpleAMS::Document::Generics::Generic
|
12
10
|
end
|
13
11
|
end
|
14
|
-
|
15
|
-
|
@@ -1,23 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
attr_reader :name
|
1
|
+
class SimpleAMS::Document::PrimaryId
|
2
|
+
attr_reader :name
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
def initialize(options)
|
5
|
+
@options = options
|
6
|
+
@name = options.primary_id.name
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
9
|
+
def value
|
10
|
+
if @options.serializer.respond_to?(name)
|
11
|
+
@options.serializer.send(name)
|
12
|
+
else
|
13
|
+
@options.resource.send(name)
|
16
14
|
end
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
end
|
17
|
+
def options
|
18
|
+
@options.primary_id.options
|
21
19
|
end
|
22
20
|
end
|
23
|
-
|
@@ -1,125 +1,115 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
#TODO: Add memoization for the relations object (iteration + access)
|
4
|
-
module SimpleAMS
|
5
|
-
class Document::Relations
|
6
|
-
include Enumerable
|
7
|
-
|
8
|
-
def initialize(options, relations)
|
9
|
-
@options = options
|
10
|
-
@relations = relations
|
11
|
-
@serializer = options.serializer
|
12
|
-
@resource = options.resource
|
13
|
-
end
|
1
|
+
require 'simple_ams'
|
14
2
|
|
15
|
-
|
16
|
-
|
17
|
-
|
3
|
+
# TODO: Add memoization for the relations object (iteration + access)
|
4
|
+
class SimpleAMS::Document::Relations
|
5
|
+
include Enumerable
|
18
6
|
|
19
|
-
|
20
|
-
|
7
|
+
def initialize(options, relations)
|
8
|
+
@options = options
|
9
|
+
@relations = relations
|
10
|
+
@serializer = options.serializer
|
11
|
+
@resource = options.resource
|
12
|
+
end
|
21
13
|
|
22
|
-
|
23
|
-
|
14
|
+
def [](key)
|
15
|
+
found = relations.find { |relation| relation.name == key }
|
16
|
+
return nil unless found
|
24
17
|
|
25
|
-
|
26
|
-
|
27
|
-
}
|
18
|
+
relation_for(found)
|
19
|
+
end
|
28
20
|
|
29
|
-
|
30
|
-
|
21
|
+
def each
|
22
|
+
return enum_for(:each) unless block_given?
|
31
23
|
|
32
|
-
|
33
|
-
|
24
|
+
relations.each do |relation|
|
25
|
+
yield relation_for(relation)
|
34
26
|
end
|
35
27
|
|
36
|
-
|
37
|
-
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def empty?
|
32
|
+
relations.length.zero?
|
33
|
+
end
|
34
|
+
|
35
|
+
def available
|
36
|
+
return @available ||= [] if relations.available.empty?
|
37
|
+
|
38
|
+
@available ||= self.class.new(options, relations.available)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
attr_reader :options, :relations, :serializer, :resource
|
44
|
+
|
45
|
+
def relation_for(relation)
|
46
|
+
relation_value = relation_value_for(relation.name)
|
47
|
+
|
48
|
+
renderer_klass_for(relation, relation_value).new(
|
49
|
+
SimpleAMS::Options.new(
|
50
|
+
relation_value, **relation_options_for(relation, relation_value)
|
51
|
+
),
|
52
|
+
SimpleAMS::Options.new(
|
53
|
+
resource,
|
54
|
+
injected_options: {
|
55
|
+
serializer: relation.embedded
|
56
|
+
},
|
57
|
+
allowed_options: relation.embedded.options
|
58
|
+
)
|
59
|
+
)
|
60
|
+
end
|
38
61
|
|
39
|
-
|
62
|
+
# TODO: rename that to relation and existing relation to relationship
|
63
|
+
def relation_value_for(name)
|
64
|
+
if serializer.respond_to?(name)
|
65
|
+
serializer.send(name)
|
66
|
+
else
|
67
|
+
resource.send(name)
|
40
68
|
end
|
69
|
+
end
|
41
70
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
injected_options: {
|
55
|
-
serializer: relation.embedded
|
56
|
-
},
|
57
|
-
allowed_options: relation.embedded.options
|
58
|
-
}
|
59
|
-
)
|
71
|
+
# 3 options are merged:
|
72
|
+
# *user injected when instantiating the SimpleAMS class
|
73
|
+
# *relation options injected from parent serializer
|
74
|
+
# *serializer class options
|
75
|
+
# rubocop:disable Lint/UnderscorePrefixedVariableName
|
76
|
+
def relation_options_for(relation, relation_value)
|
77
|
+
_relation_options = {
|
78
|
+
injected_options: (relation.options || {}).merge(
|
79
|
+
options.relation_options_for(
|
80
|
+
relation.name
|
81
|
+
).reject { |_k, v| v.nil? }.merge(
|
82
|
+
expose: options.expose
|
60
83
|
)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
def relation_value_for(name)
|
65
|
-
if serializer.respond_to?(name)
|
66
|
-
serializer.send(name)
|
67
|
-
else
|
68
|
-
resource.send(name)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
#4 options are merged:
|
73
|
-
# *user injected when instantiating the SimpleAMS class
|
74
|
-
# *relation options injected from parent serializer
|
75
|
-
# *serializer class options
|
76
|
-
def relation_options_for(relation, relation_value)
|
77
|
-
_relation_options = {
|
78
|
-
injected_options: (relation.options || {}).merge(
|
79
|
-
options.relation_options_for(
|
80
|
-
relation.name
|
81
|
-
).select{|k, v| !v.nil?}.merge(
|
82
|
-
expose: options.expose
|
83
|
-
)
|
84
|
-
).merge(
|
85
|
-
_internal: {
|
86
|
-
module: serializer.class.to_s.rpartition('::')[0]
|
87
|
-
}
|
88
|
-
)
|
84
|
+
).merge(
|
85
|
+
_internal: {
|
86
|
+
module: serializer.class.to_s.rpartition('::')[0]
|
89
87
|
}
|
88
|
+
)
|
89
|
+
}
|
90
|
+
|
91
|
+
if relation.collection? || relation_value.respond_to?(:each)
|
92
|
+
# TODO: deep merge, can we automate this somehow ?
|
93
|
+
_relation_options[:injected_options][:collection] = {
|
94
|
+
name: relation.name
|
95
|
+
}.merge(_relation_options[:injected_options][:collection] || {})
|
96
|
+
else
|
97
|
+
_relation_options[:injected_options][:name] = relation.name
|
98
|
+
end
|
90
99
|
|
91
|
-
|
92
|
-
#TODO: deep merge, can we automate this somehow ?
|
93
|
-
_relation_options[:injected_options][:collection] = {
|
94
|
-
name: relation.name
|
95
|
-
}.merge(_relation_options[:injected_options][:collection] || {})
|
96
|
-
else
|
97
|
-
_relation_options[:injected_options][:name] = relation.name
|
98
|
-
end
|
99
|
-
|
100
|
-
return _relation_options
|
101
|
-
end
|
102
|
-
=begin
|
103
|
-
def embedded_relation_options_for(relation)
|
104
|
-
_relation_options = relation_options_for(relation).merge(
|
105
|
-
allowed_options: relation.embedded.options
|
106
|
-
)
|
107
|
-
_relation_options[:injected_options][:serializer] = relation.embedded
|
108
|
-
|
109
|
-
return _relation_options
|
110
|
-
end
|
111
|
-
=end
|
112
|
-
|
113
|
-
def renderer_klass_for(relation, relation_value)
|
114
|
-
return SimpleAMS::Document::Folder if relation.collection?
|
115
|
-
return SimpleAMS::Document::Folder if relation_value.respond_to?(:each)
|
116
|
-
return SimpleAMS::Document
|
117
|
-
end
|
118
|
-
|
119
|
-
=begin TODO: Add that as public method, should help performance in edge cases
|
120
|
-
def relationship_info_for(name)
|
121
|
-
relations.find{|i| i.name == name}
|
122
|
-
end
|
123
|
-
=end
|
100
|
+
_relation_options
|
124
101
|
end
|
102
|
+
# rubocop:enable Lint/UnderscorePrefixedVariableName
|
103
|
+
|
104
|
+
def renderer_klass_for(relation, relation_value)
|
105
|
+
return SimpleAMS::Document::Folder if relation.collection?
|
106
|
+
return SimpleAMS::Document::Folder if relation_value.respond_to?(:each)
|
107
|
+
|
108
|
+
SimpleAMS::Document
|
109
|
+
end
|
110
|
+
|
111
|
+
# TODO: Add that as public method, should help performance in edge cases
|
112
|
+
# def relationship_info_for(name)
|
113
|
+
# relations.find{|i| i.name == name}
|
114
|
+
# end
|
125
115
|
end
|