Skip to content

Commit 42269e9

Browse files
author
Abderrahmane Boudi
committed
Fire hooks before validation and rename it into after_graph_persist
1 parent 9c9c769 commit 42269e9

File tree

8 files changed

+116
-26
lines changed

8 files changed

+116
-26
lines changed

lib/graphiti/resource.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ def resolve(scope)
112112
adapter.resolve(scope)
113113
end
114114

115-
def before_validation(model, metadata)
116-
hooks = self.class.config[:before_validation][metadata[:method]] || []
115+
def after_graph_persist(model, metadata)
116+
hooks = self.class.config[:after_graph_persist][metadata[:method]] || []
117117
hooks.each do |hook|
118118
instance_exec(model, metadata, &hook)
119119
end

lib/graphiti/resource/configuration.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def config
186186
sort_all: nil,
187187
sorts: {},
188188
pagination: nil,
189-
before_validation: {},
189+
after_graph_persist: {},
190190
before_commit: {},
191191
after_commit: {},
192192
attributes: {},

lib/graphiti/resource/dsl.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ def default_filter(name = nil, &blk)
8181
}
8282
end
8383

84-
def before_validation(only: [:create, :update, :destroy], &blk)
84+
def after_graph_persist(only: [:create, :update, :destroy], &blk)
8585
Array(only).each do |verb|
86-
config[:before_validation][verb] ||= []
87-
config[:before_validation][verb] << blk
86+
config[:after_graph_persist][verb] ||= []
87+
config[:after_graph_persist][verb] << blk
8888
end
8989
end
9090

lib/graphiti/resource_proxy.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,10 @@ def destroy
121121
metadata = {method: :destroy}
122122
model = @resource.destroy(@query.filters[:id], metadata)
123123
model.instance_variable_set(:@__serializer_klass, @resource.serializer)
124+
@resource.after_graph_persist(model, metadata)
124125
validator = ::Graphiti::Util::ValidationResponse.new \
125126
model, @payload
126127
validator.validate!
127-
# FIXME: I don't know in which scenarios the following line is needed!
128-
# @resource.before_validation(model, metadata)
129128
@resource.before_commit(model, metadata)
130129

131130
{result: validator}
@@ -163,6 +162,7 @@ def persist
163162
transaction_response = @resource.transaction do
164163
::Graphiti::Util::TransactionHooksRecorder.record do
165164
model = yield
165+
::Graphiti::Util::TransactionHooksRecorder.run_graph_persist_hooks
166166
validator = ::Graphiti::Util::ValidationResponse.new \
167167
model, @payload
168168
validator.validate!

lib/graphiti/util/persistence.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ def run
6060

6161
post_process(persisted, parents)
6262
post_process(persisted, children)
63-
before_validation = -> { @resource.before_validation(persisted, metadata) }
64-
add_hook(before_validation, :before_validation)
63+
after_graph_persist = -> { @resource.after_graph_persist(persisted, metadata) }
64+
add_hook(after_graph_persist, :after_graph_persist)
6565
before_commit = -> { @resource.before_commit(persisted, metadata) }
6666
add_hook(before_commit, :before_commit)
6767
after_commit = -> { @resource.after_commit(persisted, metadata) }

lib/graphiti/util/transaction_hooks_recorder.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ class TransactionHooksRecorder
88
#
99
# ```ruby
1010
# TransactionHooksRecorder.record do
11-
# TransactionHooksRecorder.add(->{ do_some_stuff() }, :before_validation)
1211
# TransactionHooksRecorder.add(->{ do_stuff() }, :before_commit)
1312
# TransactionHooksRecorder.add(->{ do_more_stuff() }, :after_commit)
1413
# {
@@ -28,7 +27,6 @@ def record
2827

2928
begin
3029
result = yield
31-
run(:before_validation)
3230
run(:before_commit)
3331

3432
unless result.is_a?(::Hash)
@@ -43,6 +41,10 @@ def record
4341
end
4442
end
4543

44+
def run_graph_persist_hooks
45+
run(:after_graph_persist)
46+
end
47+
4648
# Because hooks will be added from the outer edges of
4749
# the graph, working inwards
4850
def add(prc, lifecycle_event)
@@ -61,7 +63,7 @@ def _hooks
6163

6264
def reset_hooks
6365
Thread.current[:_graphiti_hooks] = {
64-
before_validation: [],
66+
after_graph_persist: [],
6567
before_commit: [],
6668
after_commit: [],
6769
}

spec/integration/rails/persistence_spec.rb

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,94 @@
276276
end
277277
end
278278

279+
describe "after graph persisted validation" do
280+
subject(:make_request) { do_update(payload) }
281+
282+
let(:klass) do
283+
Class.new(EmployeeResource) do
284+
self.validate_endpoints = false
285+
286+
after_graph_persist do |model|
287+
model.valid?(:after_graph_persisted)
288+
end
289+
end
290+
end
291+
292+
let(:polyvalentEmployee) do
293+
Class.new(Employee) do
294+
def self.model_name
295+
ActiveModel::Name.new(self, nil, 'PolyvalentEmployee')
296+
end
297+
validates :positions, length: { minimum: 2, too_short: 'too short, minimum is 2' }, on: :after_graph_persisted
298+
end
299+
end
300+
301+
let(:employee) { Employee.create!(first_name: "Jane") }
302+
303+
let(:payload) do
304+
{
305+
data: {
306+
type: "employees",
307+
id: employee.id.to_s,
308+
relationships: {
309+
positions: {
310+
data: [
311+
{ 'temp-id': "pos1", type: "positions", method: "create" },
312+
{ 'temp-id': "pos2", type: "positions", method: "create" },
313+
],
314+
},
315+
},
316+
},
317+
included: [
318+
{
319+
'temp-id': "pos1",
320+
type: "positions",
321+
attributes: {title: "foo"},
322+
},
323+
{
324+
'temp-id': "pos2",
325+
type: "positions",
326+
attributes: {title: "bar"},
327+
},
328+
],
329+
}
330+
end
331+
332+
before do
333+
klass.model = polyvalentEmployee
334+
allow(controller).to receive(:resource) { klass }
335+
end
336+
337+
context "when valid" do
338+
it "responds with the persisted data" do
339+
make_request
340+
expect(jsonapi_included.count).to eq(2)
341+
expect(jsonapi_included.map { |inc| inc.attributes["title"] }).to eq(["foo", "bar"])
342+
end
343+
end
344+
345+
context "when validation error" do
346+
before do
347+
payload[:data][:relationships][:positions][:data].pop
348+
end
349+
350+
it "returns validation error response" do
351+
make_request
352+
expect(json["errors"].first).to match(
353+
"code" => "unprocessable_entity",
354+
"status" => "422",
355+
"source" => {"pointer" => "/data/relationships/positions"},
356+
"detail" => "Positions too short, minimum is 2",
357+
"title" => "Validation Error",
358+
"meta" => hash_including(
359+
"attribute" => "positions",
360+
"message" => "too short, minimum is 2"
361+
)
362+
)
363+
end
364+
end
365+
end
366+
279367
describe "non-writable foreign keys" do
280368
subject(:make_request) { do_update(payload) }
281369

spec/integration/rails/transaction_hooks_spec.rb

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# rubocop: disable Style/GlobalVars
22

33
if ENV["APPRAISAL_INITIALIZED"]
4-
RSpec.describe "before_validation, before_ & after_commit hooks", type: :controller do
4+
RSpec.describe "after_graph_persist, before_ & after_commit hooks", type: :controller do
55
class Callbacks
66
class << self
77
attr_accessor :fired, :in_transaction_during, :entities
@@ -27,7 +27,7 @@ def in_transaction?
2727
Callbacks.fired = {}
2828
Callbacks.in_transaction_during = {}
2929
Callbacks.entities = []
30-
$raise_on_before_validation = {employee: false}
30+
$raise_on_after_graph_persist = {employee: false}
3131
$raise_on_before_commit = {employee: true}
3232
end
3333

@@ -76,9 +76,9 @@ class EmployeeResource < ApplicationResource
7676

7777
attribute :first_name, :string
7878

79-
before_validation do |employee|
80-
Callbacks.add(:before_validation, employee)
81-
if $raise_on_before_validation[:employee]
79+
after_graph_persist do |employee|
80+
Callbacks.add(:after_graph_persist, employee)
81+
if $raise_on_after_graph_persist[:employee]
8282
raise "rollitback"
8383
end
8484
end
@@ -226,7 +226,7 @@ def json
226226
expect {
227227
post :create, params: payload
228228
}.to raise_error("whoops")
229-
expect(Callbacks.entities).to be_empty
229+
expect(Callbacks.entities).to include(:after_graph_persist)
230230
end
231231
end
232232

@@ -238,7 +238,7 @@ def json
238238
it "fires all before and after_commit hooks" do
239239
post :create, params: payload
240240
expect(Callbacks.entities).to eq([
241-
:before_validation,
241+
:after_graph_persist,
242242
:before_create,
243243
:stacked_before_create,
244244
:employee_after_create,
@@ -247,20 +247,20 @@ def json
247247
end
248248
end
249249

250-
context "when an error is raised before_validation" do
250+
context "when an error is raised after_graph_persist" do
251251
before do
252-
$raise_on_before_validation = {employee: true}
252+
$raise_on_after_graph_persist = {employee: true}
253253
end
254254

255255
it "does not run before_commit callbacks" do
256256
expect_any_instance_of(Graphiti::Util::ValidationResponse)
257-
.to receive(:validate!)
257+
.to_not receive(:validate!)
258258
expect {
259259
post :create, params: payload
260260
}.to raise_error("rollitback")
261261
expect(Employee.count).to be_zero
262262
expect(Callbacks.entities.length).to eq(1)
263-
expect(Callbacks.fired[:before_validation]).to be_a(Employee)
263+
expect(Callbacks.fired[:after_graph_persist]).to be_a(Employee)
264264
end
265265
end
266266
end
@@ -307,7 +307,7 @@ def json
307307
post :create, params: payload
308308

309309
expect(Callbacks.entities).to eq([
310-
:before_validation,
310+
:after_graph_persist,
311311
:before_create,
312312
:stacked_before_create,
313313
:before_position,
@@ -337,7 +337,7 @@ def json
337337
expect(Callbacks.fired[:employee_after_create_eval_test]).to be_a(IntegrationHooks::EmployeeResource)
338338
end
339339

340-
it "can access children resources from before_validation" do
340+
it "can access children resources from after_graph_persist" do
341341
post :create, params: payload
342342
expect(Callbacks.fired[:employee_after_create].positions.length).to eq(1)
343343
expect(Callbacks.fired[:employee_after_create].positions[0]).to be_a(Position)

0 commit comments

Comments
 (0)