Commit 1be3e32c8fa30dc0c990efbb0cee829546733a22
Committed by
Robert Lail
1 parent
6a9f6310
Exists in
master
and in
1 other branch
Add a simple API for returning XML or JSON of problems
- Use RABL to render response - Use Devise's token authentication
Showing
8 changed files
with
127 additions
and
0 deletions
Show diff stats
Gemfile
| @@ -38,6 +38,7 @@ platform :ruby do | @@ -38,6 +38,7 @@ platform :ruby do | ||
| 38 | end | 38 | end |
| 39 | 39 | ||
| 40 | gem 'ri_cal' | 40 | gem 'ri_cal' |
| 41 | +gem 'rabl' | ||
| 41 | gem 'yajl-ruby' | 42 | gem 'yajl-ruby' |
| 42 | 43 | ||
| 43 | group :development, :test do | 44 | group :development, :test do |
| @@ -46,6 +47,7 @@ group :development, :test do | @@ -46,6 +47,7 @@ group :development, :test do | ||
| 46 | unless ENV["CI"] | 47 | unless ENV["CI"] |
| 47 | gem 'ruby-debug', :platform => :mri_18 | 48 | gem 'ruby-debug', :platform => :mri_18 |
| 48 | gem 'debugger', :platform => :mri_19 | 49 | gem 'debugger', :platform => :mri_19 |
| 50 | + gem 'pry' | ||
| 49 | end | 51 | end |
| 50 | # gem 'rpm_contrib' | 52 | # gem 'rpm_contrib' |
| 51 | # gem 'newrelic_rpm' | 53 | # gem 'newrelic_rpm' |
Gemfile.lock
| @@ -55,6 +55,7 @@ GEM | @@ -55,6 +55,7 @@ GEM | ||
| 55 | xpath (~> 0.1.4) | 55 | xpath (~> 0.1.4) |
| 56 | childprocess (0.3.5) | 56 | childprocess (0.3.5) |
| 57 | ffi (~> 1.0, >= 1.0.6) | 57 | ffi (~> 1.0, >= 1.0.6) |
| 58 | + coderay (1.0.6) | ||
| 58 | columnize (0.3.6) | 59 | columnize (0.3.6) |
| 59 | crack (0.3.1) | 60 | crack (0.3.1) |
| 60 | css_parser (1.2.6) | 61 | css_parser (1.2.6) |
| @@ -127,6 +128,7 @@ GEM | @@ -127,6 +128,7 @@ GEM | ||
| 127 | i18n (>= 0.4.0) | 128 | i18n (>= 0.4.0) |
| 128 | mime-types (~> 1.16) | 129 | mime-types (~> 1.16) |
| 129 | treetop (~> 1.4.8) | 130 | treetop (~> 1.4.8) |
| 131 | + method_source (0.7.1) | ||
| 130 | mime-types (1.19) | 132 | mime-types (1.19) |
| 131 | mongo (1.6.2) | 133 | mongo (1.6.2) |
| 132 | bson (~> 1.6.2) | 134 | bson (~> 1.6.2) |
| @@ -187,6 +189,13 @@ GEM | @@ -187,6 +189,13 @@ GEM | ||
| 187 | premailer (1.7.3) | 189 | premailer (1.7.3) |
| 188 | css_parser (>= 1.1.9) | 190 | css_parser (>= 1.1.9) |
| 189 | htmlentities (>= 4.0.0) | 191 | htmlentities (>= 4.0.0) |
| 192 | + pry (0.9.9.6) | ||
| 193 | + coderay (~> 1.0.5) | ||
| 194 | + method_source (~> 0.7.1) | ||
| 195 | + slop (>= 2.4.4, < 3) | ||
| 196 | + rabl (0.6.13) | ||
| 197 | + activesupport (>= 2.3.14) | ||
| 198 | + multi_json (~> 1.0) | ||
| 190 | rack (1.4.1) | 199 | rack (1.4.1) |
| 191 | rack-cache (1.2) | 200 | rack-cache (1.2) |
| 192 | rack (>= 0.4) | 201 | rack (>= 0.4) |
| @@ -248,6 +257,7 @@ GEM | @@ -248,6 +257,7 @@ GEM | ||
| 248 | libwebsocket (~> 0.1.3) | 257 | libwebsocket (~> 0.1.3) |
| 249 | multi_json (~> 1.0) | 258 | multi_json (~> 1.0) |
| 250 | rubyzip | 259 | rubyzip |
| 260 | + slop (2.4.4) | ||
| 251 | sprockets (2.1.3) | 261 | sprockets (2.1.3) |
| 252 | hike (~> 1.2) | 262 | hike (~> 1.2) |
| 253 | rack (~> 1.0) | 263 | rack (~> 1.0) |
| @@ -314,6 +324,8 @@ DEPENDENCIES | @@ -314,6 +324,8 @@ DEPENDENCIES | ||
| 314 | omniauth-github | 324 | omniauth-github |
| 315 | oruen_redmine_client | 325 | oruen_redmine_client |
| 316 | pivotal-tracker | 326 | pivotal-tracker |
| 327 | + pry | ||
| 328 | + rabl | ||
| 317 | rack-ssl-enforcer | 329 | rack-ssl-enforcer |
| 318 | rails (= 3.2.6) | 330 | rails (= 3.2.6) |
| 319 | rails_autolink (~> 1.0.9) | 331 | rails_autolink (~> 1.0.9) |
| @@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
| 1 | +class Api::V1::ProblemsController < ApplicationController | ||
| 2 | + | ||
| 3 | + def index | ||
| 4 | + if params.key?(:start_date) && params.key?(:end_date) | ||
| 5 | + start_date = Date.parse(params[:start_date]) | ||
| 6 | + end_date = Date.parse(params[:end_date]) | ||
| 7 | + @problems = Problem.in_date_range(start_date..end_date) | ||
| 8 | + else | ||
| 9 | + @problems = Problem.all | ||
| 10 | + end | ||
| 11 | + end | ||
| 12 | + | ||
| 13 | +end |
app/models/problem.rb
| @@ -32,6 +32,7 @@ class Problem | @@ -32,6 +32,7 @@ class Problem | ||
| 32 | index :last_notice_at | 32 | index :last_notice_at |
| 33 | index :first_notice_at | 33 | index :first_notice_at |
| 34 | index :last_deploy_at | 34 | index :last_deploy_at |
| 35 | + index :resolved_at | ||
| 35 | index :notices_count | 36 | index :notices_count |
| 36 | 37 | ||
| 37 | belongs_to :app | 38 | belongs_to :app |
| @@ -106,6 +107,10 @@ class Problem | @@ -106,6 +107,10 @@ class Problem | ||
| 106 | else raise("\"#{sort}\" is not a recognized sort") | 107 | else raise("\"#{sort}\" is not a recognized sort") |
| 107 | end | 108 | end |
| 108 | end | 109 | end |
| 110 | + | ||
| 111 | + def self.in_date_range(date_range) | ||
| 112 | + where(:first_notice_at.lte => date_range.end).where("$or" => [{:resolved_at => nil}, {:resolved_at.gte => date_range.begin}]) | ||
| 113 | + end | ||
| 109 | 114 | ||
| 110 | 115 | ||
| 111 | def reset_cached_attributes | 116 | def reset_cached_attributes |
| @@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
| 1 | +Rabl.configure do |config| | ||
| 2 | + # Commented as these are defaults | ||
| 3 | + # config.cache_all_output = false | ||
| 4 | + # config.cache_sources = Rails.env != 'development' # Defaults to false | ||
| 5 | + # config.cache_engine = Rabl::CacheEngine.new # Defaults to Rails cache | ||
| 6 | + # config.escape_all_output = false | ||
| 7 | + # config.json_engine = nil # Any multi\_json engines | ||
| 8 | + # config.msgpack_engine = nil # Defaults to ::MessagePack | ||
| 9 | + # config.bson_engine = nil # Defaults to ::BSON | ||
| 10 | + # config.plist_engine = nil # Defaults to ::Plist::Emit | ||
| 11 | + # config.include_json_root = true | ||
| 12 | + # config.include_msgpack_root = true | ||
| 13 | + # config.include_bson_root = true | ||
| 14 | + # config.include_plist_root = true | ||
| 15 | + # config.include_xml_root = false | ||
| 16 | + # config.include_child_root = true | ||
| 17 | + # config.enable_json_callbacks = false | ||
| 18 | + # config.xml_options = { :dasherize => true, :skip_types => false } | ||
| 19 | + # config.view_paths = [] | ||
| 20 | +end |
config/routes.rb
| @@ -41,6 +41,12 @@ Errbit::Application.routes.draw do | @@ -41,6 +41,12 @@ Errbit::Application.routes.draw do | ||
| 41 | resources :deploys, :only => [:index] | 41 | resources :deploys, :only => [:index] |
| 42 | end | 42 | end |
| 43 | 43 | ||
| 44 | + namespace :api do | ||
| 45 | + namespace :v1 do | ||
| 46 | + resources :problems, :only => [:index] | ||
| 47 | + end | ||
| 48 | + end | ||
| 49 | + | ||
| 44 | root :to => 'apps#index' | 50 | root :to => 'apps#index' |
| 45 | 51 | ||
| 46 | end | 52 | end |
| @@ -0,0 +1,58 @@ | @@ -0,0 +1,58 @@ | ||
| 1 | +require 'spec_helper' | ||
| 2 | + | ||
| 3 | +describe Api::V1::ProblemsController do | ||
| 4 | + | ||
| 5 | + context "when logged in" do | ||
| 6 | + before do | ||
| 7 | + @user = Fabricate(:user) | ||
| 8 | + end | ||
| 9 | + | ||
| 10 | + describe "GET /api/v1/problems" do | ||
| 11 | + before do | ||
| 12 | + Fabricate(:problem, first_notice_at: Date.new(2012, 8, 01), resolved_at: Date.new(2012, 8, 02)) | ||
| 13 | + Fabricate(:problem, first_notice_at: Date.new(2012, 8, 01), resolved_at: Date.new(2012, 8, 21)) | ||
| 14 | + Fabricate(:problem, first_notice_at: Date.new(2012, 8, 21)) | ||
| 15 | + Fabricate(:problem, first_notice_at: Date.new(2012, 8, 30)) | ||
| 16 | + end | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + it "should return JSON if JSON is requested" do | ||
| 21 | + get :index, auth_token: @user.authentication_token, format: "json" | ||
| 22 | + lambda { JSON.load(response.body) }.should_not raise_error(JSON::ParserError) | ||
| 23 | + end | ||
| 24 | + | ||
| 25 | + it "should return XML if XML is requested" do | ||
| 26 | + get :index, auth_token: @user.authentication_token, format: "xml" | ||
| 27 | + lambda { XML::Parser.string(response.body).parse }.should_not raise_error | ||
| 28 | + end | ||
| 29 | + | ||
| 30 | + it "should return JSON by default" do | ||
| 31 | + get :index, auth_token: @user.authentication_token | ||
| 32 | + lambda { JSON.load(response.body) }.should_not raise_error(JSON::ParserError) | ||
| 33 | + end | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + describe "given a date range" do | ||
| 38 | + | ||
| 39 | + it "should return only the problems open during the date range" do | ||
| 40 | + get :index, {auth_token: @user.authentication_token, start_date: "2012-08-20", end_date: "2012-08-27"} | ||
| 41 | + response.should be_success | ||
| 42 | + problems = JSON.load response.body | ||
| 43 | + problems.length.should == 2 | ||
| 44 | + end | ||
| 45 | + | ||
| 46 | + end | ||
| 47 | + | ||
| 48 | + it "should return all problems" do | ||
| 49 | + get :index, {auth_token: @user.authentication_token} | ||
| 50 | + response.should be_success | ||
| 51 | + problems = JSON.load response.body | ||
| 52 | + problems.length.should == 4 | ||
| 53 | + end | ||
| 54 | + | ||
| 55 | + end | ||
| 56 | + end | ||
| 57 | + | ||
| 58 | +end |