Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions jsonapi-utils.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ Gem::Specification.new do |spec|

spec.add_development_dependency 'bundler', '~> 1.10'
spec.add_development_dependency 'rake', '~> 10.0'
spec.add_development_dependency 'rspec-rails', '~> 3.1'
spec.add_development_dependency 'smart_rspec', '~> 0.1.4'
spec.add_development_dependency 'sqlite3'
spec.add_development_dependency 'factory_girl', '~> 4.5'
spec.add_development_dependency 'jsonapi-resources', '~> 0.7.0'
spec.add_development_dependency 'rails', '~> 4.2'
spec.add_development_dependency 'rspec-rails', '~> 3.1'
spec.add_development_dependency 'factory_girl', '~> 4.5'
spec.add_development_dependency 'smart_rspec', '~> 0.1.4'
end
24 changes: 11 additions & 13 deletions lib/jsonapi/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,14 @@ module JSONAPI
module Utils
def self.included(base)
if base.respond_to?(:helper_method)
base.helper_method :jsonapi_serialize
base.before_action :setup_request, :check_request
base.helper_method :jsonapi_render, :jsonapi_serialize
end
end

def jsonapi_render(json:, status: nil, options: {})
setup_request

if @request.errors.present?
render_errors(@request.errors)
else
body = jsonapi_serialize(json, options)
render json: body, status: status || @_response_document.status
end
body = jsonapi_serialize(json, options)
render json: body, status: status || @_response_document.status
rescue => e
handle_exceptions(e)
ensure
Expand All @@ -28,8 +23,9 @@ def jsonapi_render(json:, status: nil, options: {})
end

def jsonapi_render_errors(exception)
error = jsonapi_format_errors(exception)
render json: { errors: error.errors }, status: error.code
result = jsonapi_format_errors(exception)
errors = result.errors
render json: { errors: errors }, status: errors.first.status
end

def jsonapi_format_errors(exception)
Expand All @@ -54,8 +50,6 @@ def jsonapi_render_not_found_with_null
end

def jsonapi_serialize(records, options = {})
setup_request

if records.is_a?(Hash)
hash = records.with_indifferent_access
records = hash_to_active_record(hash[:data], options[:model])
Expand Down Expand Up @@ -258,5 +252,9 @@ def setup_request
server_error_callbacks: (self.class.server_error_callbacks || [])
)
end

def check_request
@request.errors.blank? || render_errors(@request.errors)
end
end
end
2 changes: 1 addition & 1 deletion lib/jsonapi/utils/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module JSONAPI
module Utils
VERSION = '0.4.3'
VERSION = '0.4.4'
end
end
2 changes: 2 additions & 0 deletions spec/controllers/posts_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
require 'rspec/expectations'

describe PostsController, type: :controller do
include_context 'JSON API headers'

before(:all) { FactoryGirl.create_list(:post, 3) }

let(:fields) { (PostResource.fetchable_fields - %i(id author)).map(&:to_s) }
Expand Down
45 changes: 45 additions & 0 deletions spec/controllers/users_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
require 'spec_helper'

describe UsersController, type: :controller do
include_context 'JSON API headers'

before(:all) { FactoryGirl.create_list(:user, 3, :with_posts) }

let(:fields) { (UserResource.fetchable_fields - %i(id posts)).map(&:to_s) }
let(:relationships) { %w(posts) }
let(:attributes) { { first_name: 'Yehuda', last_name: 'Katz' } }

let(:user_params) do
{ data: { type: 'users', attributes: attributes } }
end

include_examples 'JSON API invalid request', resource: :users

Expand Down Expand Up @@ -225,4 +232,42 @@
end
end
end

describe '#create' do
it 'creates a new user' do
expect { post :create, user_params }.to change(User, :count).by(1)
expect(response).to have_http_status :created
expect(response).to have_primary_data('users')
expect(response).to have_data_attributes(fields)
expect(data['attributes']['first_name']).to eq(user_params[:data][:attributes][:first_name])
end

shared_examples_for '400 response' do |hash|
it 'renders a 400 response' do
user_params[:data][:attributes].merge!(hash)
expect { post :create, user_params }.to change(User, :count).by(0)
expect(response).to have_http_status :bad_request
expect(error['title']).to eq('Param not allowed')
expect(error['code']).to eq(105)
end
end

context 'with a not permitted param' do
it_behaves_like '400 response', foo: 'bar'
end

context 'with a param not present in resource\'s attribute list' do
it_behaves_like '400 response', admin: true
end

context 'when validation fails' do
it 'render a 422 response' do
user_params[:data][:attributes].merge!(first_name: nil)
expect { post :create, user_params }.to change(User, :count).by(0)
expect(response).to have_http_status :unprocessable_entity
expect(error['title']).to eq('Can\'t change this User')
expect(error['code']).to eq(125)
end
end
end
end
1 change: 0 additions & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,3 @@ class TestApp < Rails::Application
get :index_with_hash, to: 'posts#index_with_hash'
get :show_with_hash, to: 'posts#show_with_hash'
end

28 changes: 23 additions & 5 deletions spec/support/controllers.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'support/exceptions'

class BaseController < JSONAPI::ResourceController
include JSONAPI::Utils
protect_from_forgery with: :null_session
Expand Down Expand Up @@ -38,7 +40,7 @@ def create
jsonapi_render json: new_post, status: :created
end

private
protected

def load_user
@user = User.find(params[:user_id])
Expand All @@ -48,13 +50,29 @@ def load_user
class UsersController < BaseController
# GET /users
def index
@users = User.all
jsonapi_render json: @users
users = User.all
jsonapi_render json: users
end

# GET /users/:id
def show
@user = User.find(params[:id])
jsonapi_render json: @user
user = User.find(params[:id])
jsonapi_render json: user
end

# POST /users
def create
user = User.new(user_params)
if user.save
jsonapi_render json: user, status: :created
else
jsonapi_render_errors ::Exceptions::ActiveRecordError.new(user)
end
end

protected

def user_params
params.require(:data).require(:attributes).permit(:first_name, :last_name, :admin)
end
end
17 changes: 17 additions & 0 deletions spec/support/exceptions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Exceptions
class ActiveRecordError < ::JSONAPI::Exceptions::Error
attr_accessor :object

def initialize(object)
@object = object
end

def errors
[JSONAPI::Error.new(
code: 125,
status: :unprocessable_entity,
title: "Can't change this #{@object.class.name}",
detail: @object.errors)]
end
end
end
1 change: 1 addition & 0 deletions spec/support/models.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
create_table :users, force: true do |t|
t.string :first_name
t.string :last_name
t.boolean :admin
t.timestamps null: false
end
end
Expand Down
8 changes: 8 additions & 0 deletions spec/support/shared/jsonapi_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
shared_context 'JSON API headers' do
let(:headers) do
{ 'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json' }
end

before(:each) { request.headers.merge!(headers) }
end