graphiti 1.0.beta.15 → 1.0.beta.16
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/LICENSE.txt +1 -1
- data/lib/graphiti.rb +4 -0
- data/lib/graphiti/adapters/abstract.rb +15 -62
- data/lib/graphiti/adapters/active_record.rb +10 -0
- data/lib/graphiti/errors.rb +13 -0
- data/lib/graphiti/filter_operators.rb +1 -1
- data/lib/graphiti/railtie.rb +6 -0
- data/lib/graphiti/resource.rb +2 -12
- data/lib/graphiti/resource/configuration.rb +2 -1
- data/lib/graphiti/resource/documentation.rb +55 -0
- data/lib/graphiti/resource/persistence.rb +182 -0
- data/lib/graphiti/resource_proxy.rb +1 -2
- data/lib/graphiti/schema.rb +5 -2
- data/lib/graphiti/scoping/filter.rb +4 -28
- data/lib/graphiti/util/persistence.rb +1 -2
- data/lib/graphiti/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff5dc08a7d35f114a138a26759c857eb11a226de
|
4
|
+
data.tar.gz: 00d815886fc13aca087ce7b140fc472020cbfd5c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bff46d68fcb42853a4d9e31e169ce1a06ea6bb84007728f86cc5f3b2901a3b7b5e310c906e5ad147b14161fc215c7158dd56b92b7dd12b810fd9a599c6b7f74a
|
7
|
+
data.tar.gz: f519c2331d8c4e30550bcd5481ff07c03ab9ce020855e6b1c7993f60e94d1a12f4930a39eebb4c1c4615cb7cf588ee4127bb6c820d17d4c67ed552c4b61cf20e
|
data/LICENSE.txt
CHANGED
data/lib/graphiti.rb
CHANGED
@@ -27,6 +27,8 @@ require "graphiti/resource/configuration"
|
|
27
27
|
require "graphiti/resource/dsl"
|
28
28
|
require "graphiti/resource/interface"
|
29
29
|
require "graphiti/resource/polymorphism"
|
30
|
+
require "graphiti/resource/documentation"
|
31
|
+
require "graphiti/resource/persistence"
|
30
32
|
require "graphiti/sideload"
|
31
33
|
require "graphiti/sideload/has_many"
|
32
34
|
require "graphiti/sideload/belongs_to"
|
@@ -194,3 +196,5 @@ end
|
|
194
196
|
class Object
|
195
197
|
prepend InstanceVariableOverride
|
196
198
|
end
|
199
|
+
|
200
|
+
ActiveSupport.run_load_hooks(:graphiti, Graphiti)
|
@@ -41,7 +41,9 @@ module Graphiti
|
|
41
41
|
float: numerical_operators,
|
42
42
|
boolean: [:eq],
|
43
43
|
date: numerical_operators,
|
44
|
-
datetime: numerical_operators
|
44
|
+
datetime: numerical_operators,
|
45
|
+
hash: [:eq],
|
46
|
+
array: [:eq]
|
45
47
|
}
|
46
48
|
end
|
47
49
|
|
@@ -379,75 +381,26 @@ module Graphiti
|
|
379
381
|
end
|
380
382
|
end
|
381
383
|
|
382
|
-
# Remove the association without destroying objects
|
383
|
-
#
|
384
|
-
# This is NOT needed in the standard use case. The standard use case would be:
|
385
|
-
#
|
386
|
-
# def update(attrs)
|
387
|
-
# # attrs[:the_foreign_key] is nil, so updating the record disassociates
|
388
|
-
# end
|
389
|
-
#
|
390
|
-
# However, sometimes you need side-effect or elsewise non-standard behavior. Consider
|
391
|
-
# using {{https://github.com/mbleigh/acts-as-taggable-on acts_as_taggable_on}} gem:
|
392
|
-
#
|
393
|
-
# # Not actually needed, just an example
|
394
|
-
# def disassociate(parent, child, association_name, association_type)
|
395
|
-
# parent.tag_list.remove(child.name)
|
396
|
-
# end
|
397
|
-
#
|
398
|
-
# @example Basic accessor
|
399
|
-
# def disassociate(parent, child, association_name, association_type)
|
400
|
-
# if association_type == :has_many
|
401
|
-
# parent.send(association_name).delete(child)
|
402
|
-
# else
|
403
|
-
# child.send(:"#{association_name}=", nil)
|
404
|
-
# end
|
405
|
-
# end
|
406
|
-
#
|
407
|
-
# +association_name+ and +association_type+ come from your sideload
|
408
|
-
# configuration:
|
409
|
-
#
|
410
|
-
# allow_sideload :the_name, type: the_type do
|
411
|
-
# # ... code.
|
412
|
-
# end
|
413
|
-
#
|
414
|
-
# @param parent The parent object (via the JSONAPI 'relationships' graph)
|
415
|
-
# @param child The child object (via the JSONAPI 'relationships' graph)
|
416
|
-
# @param association_name The 'relationships' key we are processing
|
417
|
-
# @param association_type The Sideload type (see Sideload#type). Usually :has_many/:belongs_to/etc
|
418
384
|
def disassociate(parent, child, association_name, association_type)
|
419
385
|
raise 'you must override #disassociate in an adapter subclass'
|
420
386
|
end
|
421
387
|
|
422
|
-
|
423
|
-
|
424
|
-
# @return the model instance just created
|
425
|
-
# @see Resource.model
|
426
|
-
# @example ActiveRecord default
|
427
|
-
# def create(model_class, create_params)
|
428
|
-
# instance = model_class.new(create_params)
|
429
|
-
# instance.save
|
430
|
-
# instance
|
431
|
-
# end
|
432
|
-
def create(model_class, create_params)
|
433
|
-
raise 'you must override #create in an adapter subclass'
|
388
|
+
def build(model_class)
|
389
|
+
model_class.new
|
434
390
|
end
|
435
391
|
|
436
|
-
#
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
# end
|
446
|
-
def update(model_class, update_params)
|
447
|
-
raise 'you must override #update in an adapter subclass'
|
392
|
+
# TODO respond to and specific error
|
393
|
+
def assign_attributes(model_instance, attributes)
|
394
|
+
attributes.each_pair do |k, v|
|
395
|
+
model_instance.send(:"#{k}=", v)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
def save(model_instance)
|
400
|
+
raise 'you must override #save in an adapter subclass'
|
448
401
|
end
|
449
402
|
|
450
|
-
def destroy(
|
403
|
+
def destroy(model_instance)
|
451
404
|
raise 'you must override #destroy in an adapter subclass'
|
452
405
|
end
|
453
406
|
|
@@ -260,6 +260,16 @@ module Graphiti
|
|
260
260
|
model.destroy
|
261
261
|
model
|
262
262
|
end
|
263
|
+
|
264
|
+
def save(model_instance)
|
265
|
+
model_instance.save
|
266
|
+
model_instance
|
267
|
+
end
|
268
|
+
|
269
|
+
def destroy(model_instance)
|
270
|
+
model_instance.destroy
|
271
|
+
model_instance
|
272
|
+
end
|
263
273
|
end
|
264
274
|
end
|
265
275
|
end
|
data/lib/graphiti/errors.rb
CHANGED
@@ -16,6 +16,19 @@ The adapter #{@adapter.class} does not implement method '#{@method}', which was
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
class AroundCallbackProc < Base
|
20
|
+
def initialize(resource_class, method_name)
|
21
|
+
@resource_class = resource_class
|
22
|
+
@method_name = method_name
|
23
|
+
end
|
24
|
+
|
25
|
+
def message
|
26
|
+
<<-MSG
|
27
|
+
#{@resource_class}: Tried to pass block to .#{@method_name}, which only accepts a method name.
|
28
|
+
MSG
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
19
32
|
class UnsupportedOperator < Base
|
20
33
|
def initialize(resource, filter_name, supported, operator)
|
21
34
|
@resource = resource
|
@@ -5,7 +5,7 @@ module Graphiti
|
|
5
5
|
|
6
6
|
def initialize(resource, type_name, opts)
|
7
7
|
@procs = {}
|
8
|
-
defaults = resource.adapter.default_operators[type_name] || []
|
8
|
+
defaults = resource.adapter.default_operators[type_name] || [:eq]
|
9
9
|
if opts[:only]
|
10
10
|
defaults = defaults.select { |op| opts[:only].include?(op) }
|
11
11
|
end
|
data/lib/graphiti/railtie.rb
CHANGED
@@ -13,6 +13,12 @@ module Graphiti
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
initializer 'graphti.logger' do
|
17
|
+
config.after_initialize do
|
18
|
+
Graphiti.logger = ::Rails.logger
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
16
22
|
initializer 'graphiti.init' do
|
17
23
|
if ::Rails.application.config.eager_load
|
18
24
|
config.after_initialize do |app|
|
data/lib/graphiti/resource.rb
CHANGED
@@ -5,6 +5,8 @@ module Graphiti
|
|
5
5
|
include Configuration
|
6
6
|
include Sideloading
|
7
7
|
include Links
|
8
|
+
include Documentation
|
9
|
+
include Persistence
|
8
10
|
|
9
11
|
attr_reader :context
|
10
12
|
|
@@ -80,18 +82,6 @@ module Graphiti
|
|
80
82
|
end
|
81
83
|
end
|
82
84
|
|
83
|
-
def create(create_params)
|
84
|
-
adapter.create(model, create_params)
|
85
|
-
end
|
86
|
-
|
87
|
-
def update(update_params)
|
88
|
-
adapter.update(model, update_params)
|
89
|
-
end
|
90
|
-
|
91
|
-
def destroy(model)
|
92
|
-
adapter.destroy(model)
|
93
|
-
end
|
94
|
-
|
95
85
|
def associate_all(parent, children, association_name, type)
|
96
86
|
adapter.associate_all(parent, children, association_name, type)
|
97
87
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Graphiti
|
2
|
+
class Resource
|
3
|
+
module Documentation
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
class_methods do
|
7
|
+
def description=(val)
|
8
|
+
@description = val
|
9
|
+
end
|
10
|
+
|
11
|
+
def description
|
12
|
+
return @description if @description.present?
|
13
|
+
|
14
|
+
if defined?(::I18n)
|
15
|
+
desc = ::I18n.t :description,
|
16
|
+
scope: i18n_resource_scope,
|
17
|
+
default: nil
|
18
|
+
desc ||= ::I18n.t :description,
|
19
|
+
scope: i18n_type_scope,
|
20
|
+
default: nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# @api private
|
25
|
+
def attribute_description(attr_name)
|
26
|
+
desc = all_attributes[attr_name][:description]
|
27
|
+
return desc if desc.present?
|
28
|
+
|
29
|
+
if defined?(::I18n)
|
30
|
+
desc = ::I18n.t :description,
|
31
|
+
scope: [*i18n_type_scope, :attributes, attr_name],
|
32
|
+
default: nil
|
33
|
+
desc ||= ::I18n.t :description,
|
34
|
+
scope: [*i18n_resource_scope, :attributes, attr_name],
|
35
|
+
default: nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def underscored_resource_name
|
42
|
+
self.name.gsub(/Resource$/, '').underscore
|
43
|
+
end
|
44
|
+
|
45
|
+
def i18n_resource_scope
|
46
|
+
[:graphiti, :resources, underscored_resource_name]
|
47
|
+
end
|
48
|
+
|
49
|
+
def i18n_type_scope
|
50
|
+
[:graphiti, :types, type]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module Graphiti
|
2
|
+
class Resource
|
3
|
+
module Persistence
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
class_methods do
|
7
|
+
def before_attributes(method = nil, only: [:create, :update], &blk)
|
8
|
+
add_callback(:attributes, :before, method, only, &blk)
|
9
|
+
end
|
10
|
+
|
11
|
+
def after_attributes(method = nil, only: [:create, :update], &blk)
|
12
|
+
add_callback(:attributes, :after, method, only, &blk)
|
13
|
+
end
|
14
|
+
|
15
|
+
def before_save(method = nil, only: [:create, :update], &blk)
|
16
|
+
add_callback(:save, :before, method, only, &blk)
|
17
|
+
end
|
18
|
+
|
19
|
+
def after_save(method = nil, only: [:create, :update], &blk)
|
20
|
+
add_callback(:save, :after, method, only, &blk)
|
21
|
+
end
|
22
|
+
|
23
|
+
def before_destroy(method = nil, &blk)
|
24
|
+
add_callback(:destroy, :before, method, [:destroy], &blk)
|
25
|
+
end
|
26
|
+
|
27
|
+
def after_destroy(method = nil, &blk)
|
28
|
+
add_callback(:destroy, :after, method, [:destroy], &blk)
|
29
|
+
end
|
30
|
+
|
31
|
+
def around_attributes(method = nil, only: [:create, :update], &blk)
|
32
|
+
if blk
|
33
|
+
raise Errors::AroundCallbackProc.new(self, 'around_attributes')
|
34
|
+
else
|
35
|
+
add_callback(:attributes, :around, method, only, &blk)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def around_save(method = nil, only: [:create, :update], &blk)
|
40
|
+
if blk
|
41
|
+
raise Errors::AroundCallbackProc.new(self, 'around_save')
|
42
|
+
else
|
43
|
+
add_callback(:save, :around, method, only, &blk)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def around_destroy(method = nil, &blk)
|
48
|
+
if blk
|
49
|
+
raise Errors::AroundCallbackProc.new(self, 'around_destroy')
|
50
|
+
else
|
51
|
+
add_callback(:destroy, :around, method, [:destroy], &blk)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def add_callback(kind, lifecycle, method = nil, only, &blk)
|
58
|
+
config[:callbacks][kind] ||= {}
|
59
|
+
config[:callbacks][kind][lifecycle] ||= []
|
60
|
+
config[:callbacks][kind][lifecycle] << { callback: (method || blk), only: only }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def create(create_params)
|
65
|
+
model_instance = nil
|
66
|
+
|
67
|
+
run_callbacks :attributes, :create, create_params do |params|
|
68
|
+
model_instance = build(model)
|
69
|
+
assign_attributes(model_instance, params)
|
70
|
+
model_instance
|
71
|
+
end
|
72
|
+
|
73
|
+
run_callbacks :save, :create, model_instance do
|
74
|
+
model_instance = save(model_instance)
|
75
|
+
end
|
76
|
+
|
77
|
+
model_instance
|
78
|
+
end
|
79
|
+
|
80
|
+
def update(update_params)
|
81
|
+
model_instance = nil
|
82
|
+
id = update_params.delete(:id)
|
83
|
+
|
84
|
+
run_callbacks :attributes, :update, update_params do |params|
|
85
|
+
model_instance = self.class._find(params.merge(id: id)).data
|
86
|
+
assign_attributes(model_instance, params)
|
87
|
+
model_instance
|
88
|
+
end
|
89
|
+
|
90
|
+
run_callbacks :save, :update, model_instance do
|
91
|
+
model_instance = save(model_instance)
|
92
|
+
end
|
93
|
+
|
94
|
+
model_instance
|
95
|
+
end
|
96
|
+
|
97
|
+
def destroy(id)
|
98
|
+
model_instance = self.class._find(id: id).data
|
99
|
+
run_callbacks :destroy, :destroy, model_instance do
|
100
|
+
adapter.destroy(model_instance)
|
101
|
+
end
|
102
|
+
model_instance
|
103
|
+
end
|
104
|
+
|
105
|
+
def build(model)
|
106
|
+
adapter.build(model)
|
107
|
+
end
|
108
|
+
|
109
|
+
def assign_attributes(model_instance, update_params)
|
110
|
+
adapter.assign_attributes(model_instance, update_params)
|
111
|
+
end
|
112
|
+
|
113
|
+
def save(model_instance)
|
114
|
+
adapter.save(model_instance)
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def run_callbacks(kind, action, *args)
|
120
|
+
fire_around_callbacks(kind, action, *args) do |*yieldargs|
|
121
|
+
fire_callbacks(kind, :before, action, *yieldargs)
|
122
|
+
result = yield(*yieldargs)
|
123
|
+
fire_callbacks(kind, :after, action, result)
|
124
|
+
result
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def fire_callbacks(kind, lifecycle, action, *args)
|
129
|
+
if callbacks = self.class.config[:callbacks][kind]
|
130
|
+
callbacks = callbacks[lifecycle] || []
|
131
|
+
callbacks.each do |config|
|
132
|
+
callback = config[:callback]
|
133
|
+
next unless config[:only].include?(action)
|
134
|
+
|
135
|
+
if callback.respond_to?(:call)
|
136
|
+
instance_exec(*args, &callback)
|
137
|
+
else
|
138
|
+
send(callback, *args)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def fire_around_callbacks(kind, action, *args, &blk)
|
145
|
+
callbacks = self.class.config[:callbacks][kind].try(:[], :around) || []
|
146
|
+
callbacks = callbacks.select { |cb| cb[:only].include?(action) }
|
147
|
+
if callbacks.length.zero?
|
148
|
+
yield(*args)
|
149
|
+
else
|
150
|
+
prc = around_callback_proc(callbacks, 0, *args, &blk)
|
151
|
+
instance_exec(*args, &prc)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# The tricky thing here is we need to yield to the next around callback
|
156
|
+
# until there are no more callbacks, then we want to call the original block
|
157
|
+
# Also keep in mind each callback needs to yield to the next
|
158
|
+
def around_callback_proc(callbacks, index, *args, &blk)
|
159
|
+
method_name = callbacks[index][:callback]
|
160
|
+
|
161
|
+
if callbacks[index + 1]
|
162
|
+
proc do
|
163
|
+
r = nil
|
164
|
+
send(method_name, *args) do |r2|
|
165
|
+
wrapped = around_callback_proc(callbacks, index+1, r2, &blk)
|
166
|
+
r = instance_exec(r2, &wrapped)
|
167
|
+
end
|
168
|
+
r
|
169
|
+
end
|
170
|
+
else
|
171
|
+
proc do |result|
|
172
|
+
r = nil
|
173
|
+
send(callbacks[index][:callback], result) do |r2|
|
174
|
+
r = instance_exec(r2, &blk)
|
175
|
+
end
|
176
|
+
r
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -95,9 +95,8 @@ module Graphiti
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def destroy
|
98
|
-
record = data
|
99
98
|
validator = @resource.transaction do
|
100
|
-
model = @resource.destroy(
|
99
|
+
model = @resource.destroy(@query.filters[:id])
|
101
100
|
model.instance_variable_set(:@__serializer_klass, @resource.serializer)
|
102
101
|
validator = ::Graphiti::Util::ValidationResponse.new \
|
103
102
|
model, @payload
|
data/lib/graphiti/schema.rb
CHANGED
@@ -83,6 +83,7 @@ module Graphiti
|
|
83
83
|
config = {
|
84
84
|
name: r.name,
|
85
85
|
type: r.type.to_s,
|
86
|
+
description: r.description,
|
86
87
|
attributes: attributes(r),
|
87
88
|
extra_attributes: extra_attributes(r),
|
88
89
|
sorts: sorts(r),
|
@@ -116,7 +117,8 @@ module Graphiti
|
|
116
117
|
attrs[name] = {
|
117
118
|
type: config[:type].to_s,
|
118
119
|
readable: flag(config[:readable]),
|
119
|
-
writable: flag(config[:writable])
|
120
|
+
writable: flag(config[:writable]),
|
121
|
+
description: resource.attribute_description(name),
|
120
122
|
}
|
121
123
|
end
|
122
124
|
end
|
@@ -128,7 +130,8 @@ module Graphiti
|
|
128
130
|
resource.extra_attributes.each_pair do |name, config|
|
129
131
|
attrs[name] = {
|
130
132
|
type: config[:type].to_s,
|
131
|
-
readable: flag(config[:readable])
|
133
|
+
readable: flag(config[:readable]),
|
134
|
+
description: resource.attribute_description(name),
|
132
135
|
}
|
133
136
|
end
|
134
137
|
end
|
@@ -1,32 +1,7 @@
|
|
1
1
|
module Graphiti
|
2
|
-
# Apply filtering logic to the scope
|
3
|
-
#
|
4
|
-
# If the user requests to filter a field that has not been allowlisted,
|
5
|
-
# a +Graphiti::Errors::BadFilter+ error will be raised.
|
6
|
-
#
|
7
|
-
# allow_filter :title # :title now allowlisted
|
8
|
-
#
|
9
|
-
# If the user requests a filter field that has been allowlisted, but
|
10
|
-
# does not pass the associated `+:if+ clause, +BadFilter+ will be raised.
|
11
|
-
#
|
12
|
-
# allow_filter :title, if: :admin?
|
13
|
-
#
|
14
|
-
# This will also honor filter aliases.
|
15
|
-
#
|
16
|
-
# # GET /posts?filter[headline]=foo will filter on title
|
17
|
-
# allow_filter :title, aliases: [:headline]
|
18
|
-
#
|
19
|
-
# @see Adapters::Abstract#filter
|
20
|
-
# @see Adapters::ActiveRecord#filter
|
21
|
-
# @see Resource.allow_filter
|
22
2
|
class Scoping::Filter < Scoping::Base
|
23
3
|
include Scoping::Filterable
|
24
4
|
|
25
|
-
# Apply the filtering logic.
|
26
|
-
#
|
27
|
-
# Loop and parse all requested filters, taking into account guards and
|
28
|
-
# aliases. If valid, call either the default or custom filtering logic.
|
29
|
-
# @return the scope we are chaining/modifying
|
30
5
|
def apply
|
31
6
|
if missing_required_filters.any?
|
32
7
|
raise Errors::RequiredFilter.new(resource, missing_required_filters)
|
@@ -47,8 +22,6 @@ module Graphiti
|
|
47
22
|
private
|
48
23
|
|
49
24
|
def filter_scope(filter, operator, value)
|
50
|
-
operator = operator.to_s.gsub('!', 'not_').to_sym
|
51
|
-
|
52
25
|
if custom_scope = filter.values[0][:operators][operator]
|
53
26
|
custom_scope.call(@scope, value, resource.context)
|
54
27
|
else
|
@@ -73,6 +46,7 @@ module Graphiti
|
|
73
46
|
filter_param.each_pair do |param_name, param_value|
|
74
47
|
filter = find_filter!(param_name)
|
75
48
|
value, operator = normalize_param(filter, param_value)
|
49
|
+
operator = operator.to_s.gsub('!', 'not_').to_sym
|
76
50
|
validate_operator(filter, operator)
|
77
51
|
value = parse_string_value(filter.values[0], value) if value.is_a?(String)
|
78
52
|
validate_singular(resource, filter, value)
|
@@ -98,7 +72,9 @@ module Graphiti
|
|
98
72
|
end
|
99
73
|
|
100
74
|
def normalize_param(filter, param_value)
|
101
|
-
|
75
|
+
unless param_value.is_a?(Hash) && param_value.present?
|
76
|
+
param_value = { eq: param_value }
|
77
|
+
end
|
102
78
|
value = param_value.values.first
|
103
79
|
operator = param_value.keys.first
|
104
80
|
|
@@ -149,8 +149,7 @@ class Graphiti::Util::Persistence
|
|
149
149
|
def persist_object(method, attributes)
|
150
150
|
case method
|
151
151
|
when :destroy
|
152
|
-
|
153
|
-
call_resource_method(:destroy, model, @caller_model)
|
152
|
+
call_resource_method(:destroy, attributes[:id], @caller_model)
|
154
153
|
when :update, nil, :disassociate
|
155
154
|
call_resource_method(:update, attributes, @caller_model)
|
156
155
|
else
|
data/lib/graphiti/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphiti
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.beta.
|
4
|
+
version: 1.0.beta.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lee Richmond
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jsonapi-serializable
|
@@ -280,9 +280,11 @@ files:
|
|
280
280
|
- lib/graphiti/renderer.rb
|
281
281
|
- lib/graphiti/resource.rb
|
282
282
|
- lib/graphiti/resource/configuration.rb
|
283
|
+
- lib/graphiti/resource/documentation.rb
|
283
284
|
- lib/graphiti/resource/dsl.rb
|
284
285
|
- lib/graphiti/resource/interface.rb
|
285
286
|
- lib/graphiti/resource/links.rb
|
287
|
+
- lib/graphiti/resource/persistence.rb
|
286
288
|
- lib/graphiti/resource/polymorphism.rb
|
287
289
|
- lib/graphiti/resource/sideloading.rb
|
288
290
|
- lib/graphiti/resource_proxy.rb
|