Skip to content

Instantly share code, notes, and snippets.

@we4tech
Last active August 29, 2015 14:02
Show Gist options
  • Save we4tech/2253abf52aeea6d91bec to your computer and use it in GitHub Desktop.
Save we4tech/2253abf52aeea6d91bec to your computer and use it in GitHub Desktop.
A simple and quick way to generate restful api for any model.
# spec/support/shared/common_api_response.rb
shared_examples 'common api response' do |param_key|
it 'responds in json' do
expect(response.content_type).to be == 'application/json'
end
it "assigns #{param_key}" do
expect(assigns(param_key.to_sym)).not_to be_nil
end
end
# Example usages
module Api
module V1
class VideosController < ApiController
include RestfulApi
protected
def video_params
params.require(:video).permit(....)
end
def resource_class
Video
end
def resource_uri(v)
api_v1_video_path(v.id)
end
end
end
end
# This should be under app/controllers/concerns/restful_api.rb
module RestfulApi
extend ActiveSupport::Concern
included do
before_filter :load_resource
before_filter :load_resources, only: [:index]
respond_to :json
end
def create
resource = set_ivar_resource(resource_class.new(resource_params))
resource.save
respond_with resource, location: resource_uri(resource)
end
def update
get_ivar_resource.update_attributes resource_params
respond_with get_ivar_resource, location: resource_uri(get_ivar_resource)
end
def show
respond_with get_ivar_resource
end
def destroy
get_ivar_resource.destroy
respond_with get_ivar_resource, location: resource_uri(get_ivar_resource)
end
def index
respond_with get_ivar_resources
end
protected
def get_ivar_resource
instance_variable_get :"@#{param_key}"
end
def get_ivar_resources
instance_variable_get :"@#{plural_key}"
end
def resource_params
self.send :"#{param_key}_params"
end
def resource_uri(resource)
raise NotImplementedError
end
def set_ivar_resource(v)
instance_variable_set :"@#{param_key}", v
end
def set_ivar_resources(v)
instance_variable_set :"@#{plural_key}", v
end
def resource_class
raise NotImplementedError
end
def param_key
ActiveModel::Naming.param_key resource_class
end
def plural_key
ActiveModel::Naming.plural resource_class
end
def load_resource
if params[:id]
set_ivar_resource resource_class.find(params[:id])
end
end
def load_resources
set_ivar_resources resource_class.all
end
end
# spec/support/shared/restful_api.rb
shared_examples 'restful api' do |param_key|
describe '#create' do
subject { post :create, param_key => params_for_create }
it "creates new #{param_key.to_s.humanize.downcase}" do
expect { subject }.
to change { param_key.to_s.classify.constantize.count }
end
it 'returns 201 status code' do
subject
expect(response.status).to be == 201
end
it 'redirects to resource path' do
subject
expect(response.location).to be == resource_uri.(assigns(param_key.to_sym))
end
end
describe '#update' do
before { resource }
subject { post :update, id: resource.id, param_key => params_for_update }
it "updates #{param_key.to_s.humanize.downcase} record" do
params_for_update.each do |key, value|
expect { subject }.
to change { resource.reload.send(key) }.
from(resource.send(key)).to(value)
end
end
it 'returns 201 status code' do
subject
expect(response.status).to be == 201
end
it 'redirects to resource path' do
subject
expect(response.location).to be == resource_uri.(resource)
end
end
describe '#show' do
before { resource }
let(:data) { JSON.parse response.body }
subject { get :show, id: resource.id }
before { subject }
it "assigns #{param_key}" do
expect(assigns(param_key.to_sym)).to be == resource
end
it 'assigns same object' do
expect(data['id']).to be == resource.id.to_s
end
it_behaves_like 'common api response', param_key
it "assigns same #{param_key}" do
expect(assigns(param_key.to_sym)).to be == resource
end
end
describe '#destroy' do
before { resource }
it "deletes an existing #{param_key.to_s.humanize.downcase}" do
expect { delete :destroy, id: resource.id }.
to change { param_key.to_s.classify.constantize.count }
end
end
describe '#index' do
before { resources }
subject { get :index }
before { subject }
it "lists all #{param_key.to_s.pluralize.humanize.downcase}" do
expect(assigns(param_key.to_s.pluralize.to_sym)).to be_present
expect(assigns(param_key.to_s.pluralize.to_sym).size).to be >= 3
end
it_behaves_like 'common api response', param_key.to_s.pluralize
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment