From 7e86e3a908f87947b7c95724d443783924d48daa Mon Sep 17 00:00:00 2001 From: Dan Hansen Date: Wed, 29 Jan 2014 17:09:52 -0800 Subject: [PATCH] Add basic limiting & ordering to payments API --- app/controllers/api/v0/payments_controller.rb | 40 +++++++- .../api/v0/payments_controller_spec.rb | 92 +++++++++++++++++-- 2 files changed, 121 insertions(+), 11 deletions(-) diff --git a/app/controllers/api/v0/payments_controller.rb b/app/controllers/api/v0/payments_controller.rb index 7fba836b..cd649aa9 100644 --- a/app/controllers/api/v0/payments_controller.rb +++ b/app/controllers/api/v0/payments_controller.rb @@ -1,6 +1,42 @@ class Api::V0::PaymentsController < Api::V0::BaseController + ALLOWED_ORDER_BY_ATTRIBUTES = ['created_at', 'updated_at', 'ct_payment_id', 'status'] + def index campaign = Campaign.find_by_id!(params[:campaign_id]) - render json: campaign.payments + resource = ApiResource.new(campaign.payments, params) + resource.apply_filters! + + render json: resource.relation end -end \ No newline at end of file + + private + + class ApiResource < Struct.new(:relation, :params) + def apply_filters! + self.relation = apply_limit!(relation) if apply_limit? + self.relation = apply_order!(relation) if apply_order? + end + + def apply_limit!(relation) + relation.limit(params[:limit]) + end + + def apply_order!(relation) + relation.order("#{params[:order_by]} #{order_direction}") + end + + def apply_order? + String(params[:order_by]).in?(ALLOWED_ORDER_BY_ATTRIBUTES) + end + + def apply_limit? + params[:limit].present? + end + + private + + def order_direction + params[:order_direction] == 'asc' ? 'asc' : 'desc' + end + end +end diff --git a/spec/controllers/api/v0/payments_controller_spec.rb b/spec/controllers/api/v0/payments_controller_spec.rb index ce496185..f49b96e8 100644 --- a/spec/controllers/api/v0/payments_controller_spec.rb +++ b/spec/controllers/api/v0/payments_controller_spec.rb @@ -8,19 +8,93 @@ let(:campaign) { create(:campaign) } let!(:first_payment) { create(:payment, campaign: campaign) } - let!(:second_payment) { create(:payment, campaign: campaign) } - subject { get :index, campaign_id: campaign.id, api_key: api_key } + def api_params(params={}) + {campaign_id: campaign.id, api_key: api_key}.merge(params) + end + + subject { get :index, api_params } + + before do + PaymentSerializer.should_receive(:new).with(first_payment, anything) + .and_return(double("serializer", serializable_hash: {payment: 1})) + end + + context 'for multiple records' do + let!(:second_payment) { create(:payment, campaign: campaign) } + before do + + PaymentSerializer.should_receive(:new).with(second_payment, anything) + .and_return(double("serializer", serializable_hash: {payment: 2})) + + end + it 'lists ALL of the payments for the campaign' do + + subject + + json = JSON.parse(response.body) + json.should == [{'payment' => 1}, {'payment' => 2}] + end + context 'ordering' do + let(:order) { '' } + let(:order_by) { 'created_at' } + + subject { get :index, api_params(order_direction: order, order_by: order_by) } + + it 'defaults to descending' do + subject + + json = JSON.parse(response.body) + json.should == [{'payment' => 2}, {'payment' => 1}] + end + + context 'ascending' do + let(:order) { 'asc' } + + it 'respects the sort order' do + subject + + json = JSON.parse(response.body) + json.should == [{'payment' => 1}, {'payment' => 2}] + end + end + + context 'descending' do + let(:order) { 'desc' } + + it 'respects the sort order' do + subject + + json = JSON.parse(response.body) + json.should == [{'payment' => 2}, {'payment' => 1}] + end + end + + context 'when ordering by a fake column' do + let(:order_by) { 'foobar' } + + it 'returns the default order' do + subject + + + json = JSON.parse(response.body) + json.should == [{'payment' => 1}, {'payment' => 2}] + end + end + end + end + + context 'limiting' do + let(:limit) { 1 } - it 'lists ALL of the payments for the campaign' do - serializer_double = double("serializer", serializable_hash: {payment: true}) - PaymentSerializer.should_receive(:new).with(first_payment, anything).and_return(serializer_double) - PaymentSerializer.should_receive(:new).with(second_payment, anything).and_return(serializer_double) + subject { get :index, api_params(limit: limit) } - subject + it 'limits the objects returned' do + subject - json = JSON.parse(response.body) - json.should == [{'payment' => true}, {'payment' => true}] + JSON.parse(response.body).size.should == 1 + end end end end +