From 2c8b32509ad6e459a4a5280d76f2eea5589dddb2 Mon Sep 17 00:00:00 2001 From: Berna Castro Date: Thu, 31 Oct 2013 20:18:33 -0200 Subject: [PATCH] Implement Endpoints for Songs --- Gemfile | 2 +- Gemfile.lock | 6 +- app/controllers/songs_controller.rb | 24 ++++++- app/models/bar.rb | 2 +- app/views/songs/base.rabl | 1 + app/views/songs/index.html.rabl | 8 ++- app/views/songs/on_sale.html.rabl | 9 +++ app/views/songs/song.rabl | 4 +- spec/controllers/songs_spec.rb | 102 ++++++++++++++++++++++++++++ spec/models/song_spec.rb | 2 +- 10 files changed, 149 insertions(+), 11 deletions(-) create mode 100644 app/views/songs/base.rabl create mode 100644 app/views/songs/on_sale.html.rabl diff --git a/Gemfile b/Gemfile index a021e13..28165db 100644 --- a/Gemfile +++ b/Gemfile @@ -23,5 +23,5 @@ group :test do end gem 'thin' -gem 'kaminari' +gem 'will_paginate', '~> 3.0' gem 'rabl' diff --git a/Gemfile.lock b/Gemfile.lock index b47456a..aa89e46 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -61,9 +61,6 @@ GEM railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) json (1.8.1) - kaminari (0.14.1) - actionpack (>= 3.0.0) - activesupport (>= 3.0.0) mail (2.5.4) mime-types (~> 1.16) treetop (~> 1.4.8) @@ -134,6 +131,7 @@ GEM uglifier (2.3.0) execjs (>= 0.3.0) json (>= 1.8.0) + will_paginate (3.0.5) PLATFORMS ruby @@ -145,7 +143,6 @@ DEPENDENCIES factory_girl faker jquery-rails - kaminari pg rabl rails (= 3.2.15) @@ -154,3 +151,4 @@ DEPENDENCIES shoulda-matchers thin uglifier (>= 1.0.3) + will_paginate (~> 3.0) diff --git a/app/controllers/songs_controller.rb b/app/controllers/songs_controller.rb index 5115a32..2dfb527 100644 --- a/app/controllers/songs_controller.rb +++ b/app/controllers/songs_controller.rb @@ -1,10 +1,32 @@ class SongsController < ApplicationController # GET /songs - def songs + def index @songs = Song.paginate(:per_page => 50, :page => params[:page]) respond_to do |format| format.html end end + + # GET /songs/on_sale + def on_sale + @songs = Song.on_sale.paginate(:per_page => 50, :page => params[:page]) + + respond_to do |format| + format.html + end + end + + # POST /songs + def create + @song = Song.new(title: params[:title], artist: params[:artist], album: params[:album], price_in_cents: params[:price]) + + respond_to do |format| + if @song.save + format.html { render 'songs/song' } + else + format.html { render json: { errors: @song.errors }, status: :unprocessable_entity } + end + end + end end diff --git a/app/models/bar.rb b/app/models/bar.rb index dd97234..b0b83ba 100644 --- a/app/models/bar.rb +++ b/app/models/bar.rb @@ -20,6 +20,6 @@ def generate_token end def downcase_name - self.name_downcased = self.name.downcase if self.name.present? + self.name_downcased = self.name.try(:downcase) end end diff --git a/app/views/songs/base.rabl b/app/views/songs/base.rabl new file mode 100644 index 0000000..298a7a3 --- /dev/null +++ b/app/views/songs/base.rabl @@ -0,0 +1 @@ +attributes :id, :title, :artist, :album, :price diff --git a/app/views/songs/index.html.rabl b/app/views/songs/index.html.rabl index c545712..43f6585 100644 --- a/app/views/songs/index.html.rabl +++ b/app/views/songs/index.html.rabl @@ -1,5 +1,9 @@ object false -child (@songs) do - extends "songs/song" +node(:pagination) do + pagination_hash(@songs) +end + +child @songs, object_root: false do + extends "songs/base" end diff --git a/app/views/songs/on_sale.html.rabl b/app/views/songs/on_sale.html.rabl new file mode 100644 index 0000000..43f6585 --- /dev/null +++ b/app/views/songs/on_sale.html.rabl @@ -0,0 +1,9 @@ +object false + +node(:pagination) do + pagination_hash(@songs) +end + +child @songs, object_root: false do + extends "songs/base" +end diff --git a/app/views/songs/song.rabl b/app/views/songs/song.rabl index 298a7a3..549e40d 100644 --- a/app/views/songs/song.rabl +++ b/app/views/songs/song.rabl @@ -1 +1,3 @@ -attributes :id, :title, :artist, :album, :price +object @song => "" + +extends "songs/base" diff --git a/spec/controllers/songs_spec.rb b/spec/controllers/songs_spec.rb index e69de29..b74b22c 100644 --- a/spec/controllers/songs_spec.rb +++ b/spec/controllers/songs_spec.rb @@ -0,0 +1,102 @@ +require 'spec_helper' + +describe 'Songs API' do + context "failed request" do + subject { JSON.parse(last_response.body)['errors'] } + + context "title, artist, album and price are not provided" do + it "responds with an error" do + post '/songs' + should have_key('title') + should have_key('artist') + should have_key('album') + should have_key('price_in_cents') + end + end + + context "name is duplicated" do + it "respond with an error" do + song = FactoryGirl.create(:song) + post "/songs", { title: song.title, album: song.album, artist: song.artist, price: 100 } + should have_key('title') + end + end + end + + context "successful request" do + subject { JSON.parse(last_response.body) } + + it "returns a song record" do + post "/songs", { title: "Awesome Song", artist: "Berna", album: "Top Hits", price: 100 } + song = Song.last + + subject['id'].should == song.id + subject['title'].should == song.title + subject['artist'].should == song.artist + subject['album'].should == song.album + subject['price'].should == song.price + end + + context "returns a list of songs in the server" do + before do + Song.destroy_all + 100.times.each do + song = FactoryGirl.create :song + end + end + + let(:url) { "/songs" } + + it "should paginate the first 50 songs" do + get url + subject.should have_key("pagination") + subject["pagination"]["total"].should == 100 + subject["pagination"]["total_pages"].should == 2 + subject["pagination"]["current_page"].should == 1 + subject.should have_key("songs") + subject["songs"].count.should eql(50) + end + + it "should paginate the second 50 songs" do + get url, { page: 2 } + subject.should have_key("pagination") + subject["pagination"]["total"].should == 100 + subject["pagination"]["total_pages"].should == 2 + subject["pagination"]["current_page"].should == 2 + subject.should have_key("songs") + subject["songs"].count.should eql(50) + end + end + + context "returns a list of songs on sale" do + before do + Song.destroy_all + 100.times.each do + song = FactoryGirl.create :song, price_in_cents: 100 + end + end + + let(:url) { "/songs/on_sale" } + + it "should paginate the first 50 songs on sale" do + get url + subject.should have_key("pagination") + subject["pagination"]["total"].should == 100 + subject["pagination"]["total_pages"].should == 2 + subject["pagination"]["current_page"].should == 1 + subject.should have_key("songs") + subject["songs"].count.should eql(50) + end + + it "should paginate the second 50 songs on sale" do + get url, { page: 2 } + subject.should have_key("pagination") + subject["pagination"]["total"].should == 100 + subject["pagination"]["total_pages"].should == 2 + subject["pagination"]["current_page"].should == 2 + subject.should have_key("songs") + subject["songs"].count.should eql(50) + end + end + end +end diff --git a/spec/models/song_spec.rb b/spec/models/song_spec.rb index 7b47deb..235be5d 100644 --- a/spec/models/song_spec.rb +++ b/spec/models/song_spec.rb @@ -2,7 +2,7 @@ describe Song do before do - Bar.delete_all + Song.delete_all end it "must have a title" do