graphiti 1.0.alpha.1 → 1.0.alpha.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -8
- data/README.md +2 -72
- data/bin/console +1 -1
- data/exe/graphiti +5 -0
- data/graphiti.gemspec +2 -2
- data/lib/generators/jsonapi/resource_generator.rb +1 -1
- data/lib/generators/jsonapi/templates/application_resource.rb.erb +0 -2
- data/lib/graphiti.rb +17 -1
- data/lib/graphiti/adapters/abstract.rb +32 -0
- data/lib/graphiti/adapters/active_record/base.rb +8 -0
- data/lib/graphiti/adapters/active_record/many_to_many_sideload.rb +2 -9
- data/lib/graphiti/cli.rb +45 -0
- data/lib/graphiti/configuration.rb +12 -0
- data/lib/graphiti/context.rb +1 -0
- data/lib/graphiti/errors.rb +105 -3
- data/lib/graphiti/filter_operators.rb +13 -3
- data/lib/graphiti/query.rb +8 -0
- data/lib/graphiti/rails.rb +1 -1
- data/lib/graphiti/railtie.rb +21 -2
- data/lib/graphiti/renderer.rb +2 -1
- data/lib/graphiti/resource.rb +11 -2
- data/lib/graphiti/resource/configuration.rb +1 -0
- data/lib/graphiti/resource/dsl.rb +4 -3
- data/lib/graphiti/resource/interface.rb +15 -0
- data/lib/graphiti/resource/links.rb +92 -0
- data/lib/graphiti/resource/polymorphism.rb +1 -0
- data/lib/graphiti/resource/sideloading.rb +13 -5
- data/lib/graphiti/resource_proxy.rb +1 -1
- data/lib/graphiti/schema.rb +169 -0
- data/lib/graphiti/schema_diff.rb +174 -0
- data/lib/graphiti/scoping/filter.rb +1 -1
- data/lib/graphiti/sideload.rb +47 -18
- data/lib/graphiti/sideload/belongs_to.rb +5 -1
- data/lib/graphiti/sideload/has_many.rb +5 -1
- data/lib/graphiti/sideload/many_to_many.rb +6 -2
- data/lib/graphiti/sideload/polymorphic_belongs_to.rb +3 -1
- data/lib/graphiti/types.rb +39 -17
- data/lib/graphiti/util/class.rb +22 -0
- data/lib/graphiti/util/hash.rb +16 -0
- data/lib/graphiti/util/hooks.rb +2 -2
- data/lib/graphiti/util/link.rb +48 -0
- data/lib/graphiti/util/serializer_relationships.rb +94 -0
- data/lib/graphiti/version.rb +1 -1
- metadata +16 -7
@@ -0,0 +1,174 @@
|
|
1
|
+
module Graphiti
|
2
|
+
class SchemaDiff
|
3
|
+
def initialize(old, new)
|
4
|
+
@old = old.deep_symbolize_keys
|
5
|
+
@new = new.deep_symbolize_keys
|
6
|
+
@errors = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def compare
|
10
|
+
compare_each if @old != @new
|
11
|
+
@errors
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def compare_each
|
17
|
+
compare_resources
|
18
|
+
compare_endpoints
|
19
|
+
compare_types
|
20
|
+
end
|
21
|
+
|
22
|
+
def compare_resources
|
23
|
+
@old[:resources].each_with_index do |r, index|
|
24
|
+
new_resource = @new[:resources].find { |n| n[:name] == r[:name] }
|
25
|
+
compare_resource(r, new_resource) do
|
26
|
+
compare_attributes(r, new_resource)
|
27
|
+
compare_extra_attributes(r, new_resource)
|
28
|
+
compare_filters(r, new_resource)
|
29
|
+
compare_relationships(r, new_resource)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def compare_resource(old_resource, new_resource)
|
35
|
+
unless new_resource
|
36
|
+
@errors << "#{old_resource[:name]} was removed."
|
37
|
+
return
|
38
|
+
end
|
39
|
+
|
40
|
+
if old_resource[:type] != new_resource[:type]
|
41
|
+
@errors << "#{old_resource[:name]} changed type from #{old_resource[:type].inspect} to #{new_resource[:type].inspect}."
|
42
|
+
end
|
43
|
+
yield
|
44
|
+
end
|
45
|
+
|
46
|
+
def compare_attributes(old_resource, new_resource)
|
47
|
+
old_resource[:attributes].each_pair do |name, old_att|
|
48
|
+
unless new_att = new_resource[:attributes][name]
|
49
|
+
@errors << "#{old_resource[:name]}: attribute #{name.inspect} was removed."
|
50
|
+
next
|
51
|
+
end
|
52
|
+
|
53
|
+
compare_attribute(old_resource[:name], name, old_att, new_att)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def compare_relationships(old_resource, new_resource)
|
58
|
+
old_resource[:relationships].each_pair do |name, old_rel|
|
59
|
+
unless new_rel = new_resource[:relationships][name]
|
60
|
+
@errors << "#{old_resource[:name]}: relationship #{name.inspect} was removed."
|
61
|
+
next
|
62
|
+
end
|
63
|
+
|
64
|
+
if new_rel[:resource] != old_rel[:resource]
|
65
|
+
@errors << "#{old_resource[:name]}: relationship #{name.inspect} changed resource from #{old_rel[:resource]} to #{new_rel[:resource]}."
|
66
|
+
end
|
67
|
+
|
68
|
+
if new_rel[:type] != old_rel[:type]
|
69
|
+
@errors << "#{old_resource[:name]}: relationship #{name.inspect} changed type from #{old_rel[:type].inspect} to #{new_rel[:type].inspect}."
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def compare_extra_attributes(old_resource, new_resource)
|
75
|
+
old_resource[:extra_attributes].each_pair do |name, old_att|
|
76
|
+
unless new_att = new_resource[:extra_attributes][name]
|
77
|
+
@errors << "#{old_resource[:name]}: extra attribute #{name.inspect} was removed."
|
78
|
+
next
|
79
|
+
end
|
80
|
+
|
81
|
+
compare_attribute(old_resource[:name], name, old_att, new_att, extra: true)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def compare_filters(old_resource, new_resource)
|
86
|
+
old_resource[:filters].each_pair do |name, old_filter|
|
87
|
+
unless new_filter = new_resource[:filters][name]
|
88
|
+
@errors << "#{old_resource[:name]}: filter #{name.inspect} was removed."
|
89
|
+
next
|
90
|
+
end
|
91
|
+
|
92
|
+
if new_filter[:type] != old_filter[:type]
|
93
|
+
@errors << "#{old_resource[:name]}: filter #{name.inspect} changed type from #{old_filter[:type].inspect} to #{new_filter[:type].inspect}."
|
94
|
+
next
|
95
|
+
end
|
96
|
+
|
97
|
+
if (diff = old_filter[:operators] - new_filter[:operators]).length > 0
|
98
|
+
diff.each do |op|
|
99
|
+
@errors << "#{old_resource[:name]}: filter #{name.inspect} removed operator #{op.inspect}."
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
if new_filter[:required] && !old_filter[:required]
|
104
|
+
@errors << "#{old_resource[:name]}: filter #{name.inspect} went from optional to required."
|
105
|
+
end
|
106
|
+
|
107
|
+
if new_filter[:guard] && !old_filter[:guard]
|
108
|
+
@errors << "#{old_resource[:name]}: filter #{name.inspect} went from unguarded to guarded."
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def compare_endpoints
|
114
|
+
@old[:endpoints].each_pair do |path, old_endpoint|
|
115
|
+
unless new_endpoint = @new[:endpoints][path]
|
116
|
+
@errors << "Endpoint \"#{path}\" was removed."
|
117
|
+
next
|
118
|
+
end
|
119
|
+
|
120
|
+
old_endpoint[:actions].each_pair do |name, old_action|
|
121
|
+
unless new_action = new_endpoint[:actions][name]
|
122
|
+
@errors << "Endpoint \"#{path}\" removed action #{name.inspect}."
|
123
|
+
next
|
124
|
+
end
|
125
|
+
|
126
|
+
if new_action[:sideload_whitelist] && !old_action[:sideload_whitelist]
|
127
|
+
@errors << "Endpoint \"#{path}\" added sideload whitelist."
|
128
|
+
end
|
129
|
+
|
130
|
+
if new_action[:sideload_whitelist]
|
131
|
+
if new_action[:sideload_whitelist] != old_action[:sideload_whitelist]
|
132
|
+
removal = Util::Hash.include_removed? \
|
133
|
+
new_action[:sideload_whitelist], old_action[:sideload_whitelist]
|
134
|
+
if removal
|
135
|
+
@errors << "Endpoint \"#{path}\" had incompatible sideload whitelist. Was #{old_action[:sideload_whitelist].inspect}, now #{new_action[:sideload_whitelist].inspect}."
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def compare_types
|
144
|
+
@old[:types].each_pair do |name, old_type|
|
145
|
+
unless new_type = @new[:types][name]
|
146
|
+
@errors << "Type #{name.inspect} was removed."
|
147
|
+
next
|
148
|
+
end
|
149
|
+
|
150
|
+
if new_type[:kind] != old_type[:kind]
|
151
|
+
@errors << "Type #{name.inspect} changed kind from #{old_type[:kind].inspect} to #{new_type[:kind].inspect}."
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def compare_attribute(resource_name, att_name, old_att, new_att, extra: false)
|
157
|
+
prefix = extra ? "extra attribute" : "attribute"
|
158
|
+
|
159
|
+
if old_att[:type] != new_att[:type]
|
160
|
+
@errors << "#{resource_name}: #{prefix} #{att_name.inspect} changed type from #{old_att[:type].inspect} to #{new_att[:type].inspect}."
|
161
|
+
end
|
162
|
+
|
163
|
+
[:readable, :writable, :sortable].each do |flag|
|
164
|
+
if [true, 'guarded'].include?(old_att[flag]) && new_att[flag] == false
|
165
|
+
@errors << "#{resource_name}: #{prefix} #{att_name.inspect} changed flag #{flag.inspect} from #{old_att[flag].inspect} to #{new_att[flag].inspect}."
|
166
|
+
end
|
167
|
+
|
168
|
+
if new_att[flag] == 'guarded' && old_att[flag] == true
|
169
|
+
@errors << "#{resource_name}: #{prefix} #{att_name.inspect} changed flag #{flag.inspect} from #{old_att[flag].inspect} to #{new_att[flag].inspect}."
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -44,7 +44,7 @@ module Graphiti
|
|
44
44
|
def filter_scope(filter, operator, value)
|
45
45
|
operator = operator.to_s.gsub('!', 'not_').to_sym
|
46
46
|
|
47
|
-
if custom_scope = filter.values
|
47
|
+
if custom_scope = filter.values[0][:operators][operator]
|
48
48
|
custom_scope.call(@scope, value, resource.context)
|
49
49
|
else
|
50
50
|
filter_via_adapter(filter, operator, value)
|
data/lib/graphiti/sideload.rb
CHANGED
@@ -9,13 +9,15 @@ module Graphiti
|
|
9
9
|
:foreign_key,
|
10
10
|
:primary_key,
|
11
11
|
:parent,
|
12
|
-
:group_name
|
12
|
+
:group_name,
|
13
|
+
:link
|
13
14
|
|
14
15
|
class_attribute :scope_proc,
|
15
16
|
:assign_proc,
|
16
17
|
:assign_each_proc,
|
17
18
|
:params_proc,
|
18
|
-
:pre_load_proc
|
19
|
+
:pre_load_proc,
|
20
|
+
:link_proc
|
19
21
|
|
20
22
|
def initialize(name, opts)
|
21
23
|
@name = name
|
@@ -28,6 +30,7 @@ module Graphiti
|
|
28
30
|
@readable = opts[:readable]
|
29
31
|
@writable = opts[:writable]
|
30
32
|
@as = opts[:as]
|
33
|
+
@link = opts[:link]
|
31
34
|
|
32
35
|
# polymorphic-specific
|
33
36
|
@group_name = opts[:group_name]
|
@@ -36,6 +39,8 @@ module Graphiti
|
|
36
39
|
if polymorphic_child?
|
37
40
|
parent.resource.polymorphic << resource_class
|
38
41
|
end
|
42
|
+
|
43
|
+
check! if defined?(::Rails)
|
39
44
|
end
|
40
45
|
|
41
46
|
def self.scope(&blk)
|
@@ -58,6 +63,30 @@ module Graphiti
|
|
58
63
|
self.pre_load_proc = blk
|
59
64
|
end
|
60
65
|
|
66
|
+
def self.link(&blk)
|
67
|
+
self.link_proc = blk
|
68
|
+
end
|
69
|
+
|
70
|
+
def check!
|
71
|
+
case type
|
72
|
+
when :has_many, :has_one
|
73
|
+
unless resource.filters[foreign_key]
|
74
|
+
raise Errors::MissingSideloadFilter.new parent_resource_class,
|
75
|
+
self, foreign_key
|
76
|
+
end
|
77
|
+
when :belongs_to
|
78
|
+
unless resource.filters[primary_key]
|
79
|
+
raise Errors::MissingSideloadFilter.new parent_resource_class,
|
80
|
+
self, primary_key
|
81
|
+
end
|
82
|
+
when :many_to_many
|
83
|
+
unless resource.filters[true_foreign_key]
|
84
|
+
raise Errors::MissingSideloadFilter.new parent_resource_class,
|
85
|
+
self, true_foreign_key
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
61
90
|
def readable?
|
62
91
|
!!@readable
|
63
92
|
end
|
@@ -66,6 +95,16 @@ module Graphiti
|
|
66
95
|
!!@writable
|
67
96
|
end
|
68
97
|
|
98
|
+
def link?
|
99
|
+
return true if link_proc
|
100
|
+
|
101
|
+
if @link.nil?
|
102
|
+
!!@parent_resource_class.autolink
|
103
|
+
else
|
104
|
+
!!@link
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
69
108
|
def polymorphic_parent?
|
70
109
|
resource.polymorphic?
|
71
110
|
end
|
@@ -116,7 +155,7 @@ module Graphiti
|
|
116
155
|
|
117
156
|
def load(parents, query)
|
118
157
|
params = load_params(parents, query)
|
119
|
-
params_proc.call(params, parents
|
158
|
+
params_proc.call(params, parents) if params_proc
|
120
159
|
opts = load_options(parents, query)
|
121
160
|
proxy = resource.class._all(params, opts, base_scope)
|
122
161
|
pre_load_proc.call(proxy) if pre_load_proc
|
@@ -157,8 +196,7 @@ module Graphiti
|
|
157
196
|
end
|
158
197
|
|
159
198
|
def resolve(parents, query)
|
160
|
-
|
161
|
-
if self.class.scope_proc || type == :many_to_many
|
199
|
+
if self.class.scope_proc
|
162
200
|
sideload_scope = fire_scope(parents)
|
163
201
|
sideload_scope = Scope.new sideload_scope,
|
164
202
|
resource,
|
@@ -261,21 +299,12 @@ module Graphiti
|
|
261
299
|
end
|
262
300
|
end
|
263
301
|
|
264
|
-
def
|
265
|
-
|
266
|
-
split = namespace.split('::')
|
267
|
-
split[0,split.length-1].join('::')
|
302
|
+
def infer_resource_class
|
303
|
+
Util::Class.infer_resource_class(parent_resource.class, name)
|
268
304
|
end
|
269
305
|
|
270
|
-
def
|
271
|
-
|
272
|
-
inferred_name = "#{name.to_s.singularize.classify}Resource"
|
273
|
-
klass = "#{namespace}::#{inferred_name}".safe_constantize
|
274
|
-
klass ||= inferred_name.safe_constantize
|
275
|
-
unless klass
|
276
|
-
raise Errors::ResourceNotFound.new(parent_resource, name)
|
277
|
-
end
|
278
|
-
klass
|
306
|
+
def namespace_for(klass)
|
307
|
+
Util::Class.namespace_for(klass)
|
279
308
|
end
|
280
309
|
end
|
281
310
|
end
|
@@ -6,10 +6,14 @@ class Graphiti::Sideload::BelongsTo < Graphiti::Sideload
|
|
6
6
|
def load_params(parents, query)
|
7
7
|
query.to_hash.tap do |hash|
|
8
8
|
hash[:filter] ||= {}
|
9
|
-
hash[:filter]
|
9
|
+
hash[:filter].merge!(base_filter(parents))
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
def base_filter(parents)
|
14
|
+
{ primary_key => ids_for_parents(parents).join(',') }
|
15
|
+
end
|
16
|
+
|
13
17
|
def assign_each(parent, children)
|
14
18
|
children.find { |c| c.send(primary_key) == parent.send(foreign_key) }
|
15
19
|
end
|
@@ -6,10 +6,14 @@ class Graphiti::Sideload::HasMany < Graphiti::Sideload
|
|
6
6
|
def load_params(parents, query)
|
7
7
|
query.to_hash.tap do |hash|
|
8
8
|
hash[:filter] ||= {}
|
9
|
-
hash[:filter]
|
9
|
+
hash[:filter].merge!(base_filter(parents))
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
def base_filter(parents)
|
14
|
+
{ foreign_key => ids_for_parents(parents).join(',') }
|
15
|
+
end
|
16
|
+
|
13
17
|
def assign_each(parent, children)
|
14
18
|
children.select { |c| c.send(foreign_key) == parent.send(primary_key) }
|
15
19
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Graphiti::Sideload::ManyToMany < Graphiti::Sideload
|
1
|
+
class Graphiti::Sideload::ManyToMany < Graphiti::Sideload::HasMany
|
2
2
|
def type
|
3
3
|
:many_to_many
|
4
4
|
end
|
@@ -11,8 +11,12 @@ class Graphiti::Sideload::ManyToMany < Graphiti::Sideload
|
|
11
11
|
foreign_key.values.first
|
12
12
|
end
|
13
13
|
|
14
|
+
def base_filter(parents)
|
15
|
+
{ true_foreign_key => ids_for_parents(parents).join(',') }
|
16
|
+
end
|
17
|
+
|
14
18
|
def infer_foreign_key
|
15
|
-
raise 'You must explicitly pass :foreign_key for many-to-many
|
19
|
+
raise 'You must explicitly pass :foreign_key for many-to-many relationships, or override in subclass to return a hash.'
|
16
20
|
end
|
17
21
|
|
18
22
|
def assign_each(parent, children)
|
@@ -23,12 +23,14 @@ class Graphiti::Sideload::PolymorphicBelongsTo < Graphiti::Sideload::BelongsTo
|
|
23
23
|
def on(name, &blk)
|
24
24
|
group = Group.new(name)
|
25
25
|
@groups << group
|
26
|
-
group.belongs_to(name.to_s.underscore.to_sym)
|
27
26
|
group
|
28
27
|
end
|
29
28
|
|
30
29
|
def apply(sideload, resource_class)
|
31
30
|
@groups.each do |group|
|
31
|
+
if group.calls.empty?
|
32
|
+
group.belongs_to(group.name.to_s.underscore.to_sym)
|
33
|
+
end
|
32
34
|
group.calls.each do |call|
|
33
35
|
args = call[1]
|
34
36
|
opts = args.extract_options!
|
data/lib/graphiti/types.rb
CHANGED
@@ -72,6 +72,8 @@ module Graphiti
|
|
72
72
|
Dry::Types['params.hash'][input].deep_symbolize_keys
|
73
73
|
end
|
74
74
|
|
75
|
+
REQUIRED_KEYS = [:params, :read, :write, :kind, :description]
|
76
|
+
|
75
77
|
def self.map
|
76
78
|
@map ||= begin
|
77
79
|
hash = {
|
@@ -79,52 +81,72 @@ module Graphiti
|
|
79
81
|
canonical_name: :integer,
|
80
82
|
params: Dry::Types['coercible.integer'],
|
81
83
|
read: Dry::Types['coercible.string'],
|
82
|
-
write: Dry::Types['coercible.integer']
|
84
|
+
write: Dry::Types['coercible.integer'],
|
85
|
+
kind: 'scalar',
|
86
|
+
description: 'Base Type. Query/persist as integer, render as string.'
|
83
87
|
},
|
84
88
|
string: {
|
85
89
|
params: Dry::Types['coercible.string'],
|
86
90
|
read: Dry::Types['coercible.string'],
|
87
|
-
write: Dry::Types['coercible.string']
|
91
|
+
write: Dry::Types['coercible.string'],
|
92
|
+
kind: 'scalar',
|
93
|
+
description: 'Base Type.'
|
88
94
|
},
|
89
95
|
integer: {
|
90
96
|
params: PresentInteger,
|
91
97
|
read: Integer,
|
92
|
-
write: Integer
|
98
|
+
write: Integer,
|
99
|
+
kind: 'scalar',
|
100
|
+
description: 'Base Type.'
|
93
101
|
},
|
94
102
|
big_decimal: {
|
95
103
|
params: ParamDecimal,
|
96
104
|
read: Dry::Types['json.decimal'],
|
97
|
-
write: Dry::Types['json.decimal']
|
105
|
+
write: Dry::Types['json.decimal'],
|
106
|
+
kind: 'scalar',
|
107
|
+
description: 'Base Type.'
|
98
108
|
},
|
99
109
|
float: {
|
100
110
|
params: Dry::Types['coercible.float'],
|
101
111
|
read: Float,
|
102
|
-
write: Float
|
112
|
+
write: Float,
|
113
|
+
kind: 'scalar',
|
114
|
+
description: 'Base Type.'
|
103
115
|
},
|
104
116
|
boolean: {
|
105
117
|
params: PresentBool,
|
106
118
|
read: Bool,
|
107
|
-
write: Bool
|
119
|
+
write: Bool,
|
120
|
+
kind: 'scalar',
|
121
|
+
description: 'Base Type.'
|
108
122
|
},
|
109
123
|
date: {
|
110
124
|
params: PresentDate,
|
111
125
|
read: Date,
|
112
|
-
write: Date
|
126
|
+
write: Date,
|
127
|
+
kind: 'scalar',
|
128
|
+
description: 'Base Type.'
|
113
129
|
},
|
114
130
|
datetime: {
|
115
131
|
params: PresentParamsDateTime,
|
116
132
|
read: ReadDateTime,
|
117
|
-
write: WriteDateTime
|
133
|
+
write: WriteDateTime,
|
134
|
+
kind: 'scalar',
|
135
|
+
description: 'Base Type.'
|
118
136
|
},
|
119
137
|
hash: {
|
120
138
|
params: PresentParamsHash,
|
121
139
|
read: Dry::Types['strict.hash'],
|
122
|
-
write: Dry::Types['strict.hash']
|
140
|
+
write: Dry::Types['strict.hash'],
|
141
|
+
kind: 'record',
|
142
|
+
description: 'Base Type.'
|
123
143
|
},
|
124
144
|
array: {
|
125
145
|
params: Dry::Types['strict.array'],
|
126
146
|
read: Dry::Types['strict.array'],
|
127
|
-
write: Dry::Types['strict.array']
|
147
|
+
write: Dry::Types['strict.array'],
|
148
|
+
kind: 'array',
|
149
|
+
description: 'Base Type.'
|
128
150
|
}
|
129
151
|
}
|
130
152
|
|
@@ -134,12 +156,16 @@ module Graphiti
|
|
134
156
|
|
135
157
|
arrays = {}
|
136
158
|
hash.each_pair do |name, map|
|
159
|
+
next if [:boolean, :hash, :array].include?(name)
|
160
|
+
|
137
161
|
arrays[:"array_of_#{name.to_s.pluralize}"] = {
|
138
162
|
canonical_name: name,
|
139
163
|
params: Dry::Types['strict.array'].of(map[:params]),
|
140
164
|
read: Dry::Types['strict.array'].of(map[:read]),
|
141
165
|
test: Dry::Types['strict.array'].of(map[:test]),
|
142
|
-
write: Dry::Types['strict.array'].of(map[:write])
|
166
|
+
write: Dry::Types['strict.array'].of(map[:write]),
|
167
|
+
kind: 'array',
|
168
|
+
description: 'Base Type.'
|
143
169
|
}
|
144
170
|
end
|
145
171
|
hash.merge!(arrays)
|
@@ -153,12 +179,8 @@ module Graphiti
|
|
153
179
|
end
|
154
180
|
|
155
181
|
def self.[]=(key, value)
|
156
|
-
unless value.is_a?(Hash)
|
157
|
-
|
158
|
-
read: value,
|
159
|
-
params: value,
|
160
|
-
test: value
|
161
|
-
}
|
182
|
+
unless value.is_a?(Hash) && (REQUIRED_KEYS - value.keys).length.zero?
|
183
|
+
raise Errors::InvalidType.new(key, value)
|
162
184
|
end
|
163
185
|
map[key.to_sym] = value
|
164
186
|
end
|