Skip to content

Commit 27afc52

Browse files
authored
Add jsonapi_destroy (#65)
1 parent a3fe664 commit 27afc52

File tree

7 files changed

+82
-21
lines changed

7 files changed

+82
-21
lines changed

gemfiles/rails_4.gemfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
source "https://rubygems.org"
44

55
gem "rails", "~> 4.1"
6-
gem "jsonapi-rails", "~> 0.3.1", require: "jsonapi/rails"
6+
gem "jsonapi-rails", "~> 0.3.1", :require => "jsonapi/rails"
77
gem "rspec-rails"
88

99
group :test do
1010
gem "pry"
11-
gem "pry-byebug", platform: [:mri]
11+
gem "pry-byebug", :platform => [:mri]
1212
gem "appraisal"
1313
gem "guard"
1414
gem "guard-rspec"
1515
end
1616

17-
gemspec path: "../"
17+
gemspec :path => "../"

gemfiles/rails_5.gemfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
source "https://rubygems.org"
44

55
gem "rails", "~> 5.0"
6-
gem "jsonapi-rails", "~> 0.3.1", require: "jsonapi/rails"
6+
gem "jsonapi-rails", "~> 0.3.1", :require => "jsonapi/rails"
77
gem "rspec-rails"
88

99
group :test do
1010
gem "pry"
11-
gem "pry-byebug", platform: [:mri]
11+
gem "pry-byebug", :platform => [:mri]
1212
gem "appraisal"
1313
gem "guard"
1414
gem "guard-rspec"
1515
end
1616

17-
gemspec path: "../"
17+
gemspec :path => "../"

lib/generators/jsonapi/templates/controller.rb.erb

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,17 @@ class <%= model_klass.name.pluralize %>Controller < ApplicationController
7979
<%- end -%>
8080
<%- if actions?('destroy') -%>
8181
<%- unless omit_comments? -%>
82-
# No need for any special logic here as no_content is jsonapi_compliant.
83-
# Customize this if you have a more complex use case.
82+
# Renders 200 OK with empty meta
83+
# http://jsonapi.org/format/#crud-deleting-responses-200
8484
<%- end -%>
8585
def destroy
86-
<%= file_name %> = <%= model_klass %>.find(params[:id])
87-
<%= file_name %>.destroy
88-
return head(:no_content)
86+
<%= file_name %>, success = jsonapi_destroy.to_a
87+
88+
if success
89+
render_jsonapi(<%= file_name %>, scope: false)
90+
else
91+
render_errors_for(<%= file_name %>)
92+
end
8993
end
9094
<%- end -%>
9195
end

lib/jsonapi_compliable/base.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,12 @@ def jsonapi_update
226226
end
227227
end
228228

229+
def jsonapi_destroy
230+
_persist do
231+
jsonapi_resource.destroy(params[:id])
232+
end
233+
end
234+
229235
# Similar to +render :json+ or +render :jsonapi+
230236
#
231237
# By default, this will "build" the scope via +#jsonapi_scope+. To avoid

lib/jsonapi_compliable/deserializer.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,18 @@ def process_relationship_datum(datum)
207207
end
208208

209209
def raw_attributes
210-
data[:attributes] || {}
210+
if data
211+
data[:attributes] || {}
212+
else
213+
{}
214+
end
211215
end
212216

213217
def raw_relationships
214-
data[:relationships] || {}
218+
if data
219+
data[:relationships] || {}
220+
else
221+
{}
222+
end
215223
end
216224
end

spec/fixtures/employee_directory.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,34 @@ class HomeOffice < ApplicationRecord
7474
end
7575

7676
class Employee < ApplicationRecord
77+
attr_accessor :force_validation_error
78+
7779
belongs_to :workspace, polymorphic: true
7880
belongs_to :classification
7981
has_many :positions
8082
validates :first_name, presence: true
83+
validates :delete_confirmation,
84+
presence: true,
85+
on: :destroy
8186

8287
has_many :employee_teams
8388
has_many :teams, through: :employee_teams
8489

8590
has_one :salary
91+
92+
before_destroy do
93+
add_validation_error if force_validation_error
94+
95+
if Rails::VERSION::MAJOR >= 5
96+
throw(:abort) if errors.present?
97+
else
98+
errors.blank?
99+
end
100+
end
101+
102+
def add_validation_error
103+
errors.add(:base, 'Forced validation error')
104+
end
86105
end
87106

88107
class Position < ApplicationRecord

spec/integration/rails/persistence_spec.rb

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,13 @@ def update
3737
end
3838

3939
def destroy
40-
employee = Employee.find(params[:id])
41-
employee.destroy
42-
render_jsonapi(employee, scope: false)
40+
employee, success = jsonapi_destroy.to_a
41+
42+
if success
43+
render json: { meta: {} }
44+
else
45+
render json: { error: employee.errors }
46+
end
4347
end
4448
end
4549

@@ -135,17 +139,37 @@ def do_put(id)
135139
end
136140

137141
describe 'basic destroy' do
138-
let(:employee) { Employee.create!(first_name: 'Joe') }
142+
let!(:employee) { Employee.create!(first_name: 'Joe') }
143+
144+
before do
145+
allow_any_instance_of(Employee)
146+
.to receive(:force_validation_error) { force_validation_error }
147+
end
148+
149+
let(:force_validation_error) { false }
139150

140151
it 'deletes the object' do
141-
delete :destroy, params: { id: employee.id }
152+
expect {
153+
delete :destroy, params: { id: employee.id }
154+
}.to change { Employee.count }.by(-1)
142155
expect { employee.reload }.to raise_error(ActiveRecord::RecordNotFound)
143156
end
144157

145-
it 'responds with object' do
158+
it 'responds with 200, empty meta' do
146159
delete :destroy, params: { id: employee.id }
147-
expect(json_item['id']).to eq(employee.id.to_s)
148-
expect(json_item['first_name']).to eq('Joe')
160+
expect(response.status).to eq(200)
161+
expect(json).to eq({ 'meta' => {} })
162+
end
163+
164+
context 'when validation errors' do
165+
let(:force_validation_error) { true }
166+
167+
it 'responds with correct error payload' do
168+
expect {
169+
delete :destroy, params: { id: employee.id }
170+
}.to_not change { Employee.count }
171+
expect(json['error']).to eq('base' => ['Forced validation error'])
172+
end
149173
end
150174
end
151175

0 commit comments

Comments
 (0)