Skip to content

Commit 7f9c328

Browse files
johvetTate Thurston
authored andcommitted
Add support for status to the error serializer
1 parent e3b604b commit 7f9c328

File tree

4 files changed

+82
-6
lines changed

4 files changed

+82
-6
lines changed

lib/jsonapi/active_model_error_serializer.rb

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,34 @@
33
module JSONAPI
44
# [ActiveModel::Errors] serializer
55
class ActiveModelErrorSerializer < ErrorSerializer
6-
attribute :status do
7-
'422'
6+
class << self
7+
##
8+
# Get the status code to render for the serializer, considering an eventual
9+
# status provided through the serializer parameters
10+
#
11+
# @param params [Hash]
12+
# The serializer parameters
13+
#
14+
# @return [Integer]
15+
# The status code to use
16+
def status_code(params)
17+
case params[:status]
18+
when Symbol
19+
Rack::Utils::SYMBOL_TO_STATUS_CODE[params[:status]]
20+
when Integer
21+
params[:status]
22+
else
23+
422
24+
end
25+
end
26+
end
27+
28+
attribute :status do |_, params|
29+
status_code(params).to_s
830
end
931

10-
attribute :title do
11-
Rack::Utils::HTTP_STATUS_CODES[422]
32+
attribute :title do |_, params|
33+
Rack::Utils::HTTP_STATUS_CODES[status_code(params)]
1234
end
1335

1436
attribute :code do |object|

lib/jsonapi/rails.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def self.add_errors_renderer!
7979

8080
JSONAPI::Rails.serializer_to_json(
8181
JSONAPI::ActiveModelErrorSerializer.new(
82-
errors, params: { model: model, model_serializer: model_serializer }
82+
errors, params: { model: model, model_serializer: model_serializer, status: options[:status] }
8383
)
8484
)
8585
end

spec/dummy.rb

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class Note < ActiveRecord::Base
4545
validates_numericality_of :quantity, less_than: 100, if: :quantity?
4646
validate :title_check
4747
belongs_to :user, required: true
48+
before_destroy :deletable?
4849

4950
def self.ransackable_associations(auth_object = nil)
5051
%w(user)
@@ -58,6 +59,13 @@ def self.ransackable_attributes(auth_object = nil)
5859
def title_check
5960
errors.add(:base, :invalid) if title == 'n/a'
6061
end
62+
63+
def deletable?
64+
return true unless title == 'Lovely'
65+
66+
errors.add(:base, "Can't delete lovely notes")
67+
throw :abort
68+
end
6169
end
6270

6371
class CustomNoteSerializer
@@ -90,7 +98,7 @@ class Dummy < Rails::Application
9098
routes.draw do
9199
scope defaults: { format: :jsonapi } do
92100
resources :users, only: [:index]
93-
resources :notes, only: [:update]
101+
resources :notes, only: [:update, :destroy]
94102
end
95103
end
96104
end
@@ -157,6 +165,15 @@ def update
157165
end
158166
end
159167

168+
def destroy
169+
note = Note.find(params[:id])
170+
if note.destroy
171+
head :no_content
172+
else
173+
render jsonapi_errors: note.errors, status: :conflict
174+
end
175+
end
176+
160177
private
161178
def render_jsonapi_internal_server_error(exception)
162179
Rails.logger.error(exception)

spec/errors_spec.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,41 @@
191191
end
192192
end
193193
end
194+
195+
describe 'DELETE /nodes/:id' do
196+
let(:note) { create_note }
197+
let(:note_id) { note.id }
198+
let(:user) { note.user }
199+
let(:user_id) { user.id }
200+
201+
context 'with a random note' do
202+
before { delete(note_path(note_id), headers: jsonapi_headers) }
203+
204+
it { expect(response).to have_http_status(:no_content) }
205+
end
206+
207+
context 'with a lovely note' do
208+
let(:errors) do
209+
{
210+
'errors' => [
211+
{
212+
'code' => 'cant_delete_lovely_notes',
213+
'detail' => "Can't delete lovely notes",
214+
'source' => { 'pointer' => '/data' },
215+
'status' => '409',
216+
'title' => 'Conflict'
217+
}
218+
]
219+
}
220+
end
221+
222+
before do
223+
note.update(title: 'Lovely')
224+
delete(note_path(note_id), headers: jsonapi_headers)
225+
end
226+
227+
it { expect(response).to have_http_status(:conflict) }
228+
it { expect(response_json).to match(errors) }
229+
end
230+
end
194231
end

0 commit comments

Comments
 (0)