* VRFS-18 completed by integrating ConnectionManager to REST API

* rescue_from used a little now; good way to handle errors
This commit is contained in:
Seth Call 2012-10-23 06:43:52 -05:00
parent 97f095fe03
commit 8837b29814
12 changed files with 129 additions and 50 deletions

View File

@ -29,6 +29,7 @@ group :development, :test do
gem 'rspec-rails', '2.11.0'
gem 'guard-rspec', '0.5.5'
gem 'jasmine'
gem 'pry'
end
# Gems used only for assets and not required

View File

@ -1,5 +1,23 @@
class ApiMusicSessionsController < ApplicationController
# TODO: roll these into a base ApiController class?s
rescue_from 'JamRuby::StateError' do |exception|
@exception = exception
render "errors/state_error.rabl", :status => 500
end
rescue_from 'JamRuby::JamArgrumentError' do |exception|
@exception = exception
render "errors/jam_argument_error.rabl", :status => 500
end
rescue_from 'JamRuby::PermissionError' do |exception|
@exception = exception
render "errors/permission_error.rabl", :status => 500
end
rescue_from 'ActiveRecord::RecordNotFound' do |exception|
render :status => 404
end
# have to be signed in currently to see this screen
before_filter :signed_in_user
@ -8,6 +26,7 @@ class ApiMusicSessionsController < ApplicationController
def initialize
@mq_router = MQRouter.new
@message_factory = MessageFactory.new
end
def index
@ -15,10 +34,26 @@ class ApiMusicSessionsController < ApplicationController
end
def create
@music_session = MusicSession.new()
@music_session.creator = current_user
@music_session.description = params[:description]
@music_session.save
ConnectionManager.active_record_transaction do |connection_manager|
client_id = params[:client_id]
if client_id.nil?
raise JamArgumentError, "client_id must be specified"
end
@music_session = MusicSession.new()
@music_session.creator = current_user
@music_session.description = params[:description]
saved = @music_session.save
if saved
# auto-join this user into the newly created session
connection_manager.join_music_session(current_user.id, client_id, @music_session.id)
end
end
respond_with @music_session, responder: ApiResponder, :location => api_session_detail_url(@music_session)
end
@ -34,33 +69,50 @@ class ApiMusicSessionsController < ApplicationController
end
def participant_show
@music_session_client = MusicSessionClient.find(params[:id])
@connection = Connection.find(params[:id])
end
def participant_create
@music_session = MusicSession.find(params[:id])
@music_session = nil
@connection = nil
client_id = params[:client_id]
@music_session_client = MusicSessionClient.new()
@music_session_client.ip_address = params[:ip_address]
@music_session_client.client_id = client_id
@music_session_client.music_session = @music_session
@music_session_client.user = current_user
saved = @music_session_client.save
ConnectionManager.active_record_transaction do |connection_manager|
@music_session = MusicSession.find(params[:id])
if saved
# send out notification to queue to the rest of the session
user_joined = @message_factory.user_joined_music_session(current_user.id, current_user.name)
@mq_router.user_publish_to_session(@music_session, current_user, user_joined, sender = {:client_id => client_id})
if @music_session.nil?
raise JamArgumentError, "no session found"
end
client_id = params[:client_id]
connection_manager.join_music_session(current_user.id, client_id, @music_session.id)
@connection = Connection.find_by_client_id(client_id)
end
respond_with @music_session_client, responder: ApiResponder, :location => api_session_participant_detail_url(@music_session_client)
# send out notification to queue to the rest of the session
user_joined = @message_factory.user_joined_music_session(current_user.id, current_user.name)
@mq_router.user_publish_to_session(@music_session, current_user, user_joined, sender = {:client_id => @connection.client_id})
respond_with @connection, responder: ApiResponder, :location => api_session_participant_detail_url(@connection.client_id)
end
def participant_delete
@music_session_client = MusicSessionClient.find(params[:id])
@music_session_client.delete
respond_with @music_session_client, responder: ApiResponder
ConnectionManager.active_record_transaction do |connection_manager|
@connection = Connection.find_by_client_id(params[:client_id])
if @connection.nil?
raise JamArgumentError, "no client found with specified client_id #{id}"
end
if @connection.user.id != current_user.id
raise PermissionError, "you do not own this connection"
end
connection_manager.leave_music_session(current_user.id, @connection.client_id, @connection.music_session_id)
end
respond_with @connection, responder: ApiResponder
end
end

View File

@ -0,0 +1,3 @@
object @music_session
extends "api_music_sessions/show"

View File

@ -1,3 +1,3 @@
object @music_session_client
object @connection
attributes :id, :ip_address, :client_id

View File

@ -2,7 +2,7 @@ object @music_session
attributes :id, :description
child(:music_session_clients => :participants) {
child(:connections => :participants) {
collection @music_sessions, :object_root => false
attributes :id, :ip_address, :client_id
}

View File

@ -0,0 +1,7 @@
object @exception
attributes :message
node "type" do
"ArgumentError"
end

View File

@ -0,0 +1,7 @@
object @exception
attributes :message
node "type" do
"PermissionError"
end

View File

@ -0,0 +1,7 @@
object @exception
attributes :message
node "type" do
"StateError"
end

View File

@ -25,8 +25,11 @@ test: &test
timeout: 5000
production:
adapter: sqlite3
database: db/production.sqlite3
adapter: postgresql
database: jam
username: postgres
password: postgres
host: localhost
pool: 5
timeout: 5000

View File

@ -26,8 +26,8 @@ SampleApp::Application.routes.draw do
scope '/api' do
# music sessions
match '/sessions/:id/participants' => 'api_music_sessions#participant_create', :via => :post
match '/participants/:id' => 'api_music_sessions#participant_show', :via => :get, :as => 'api_session_participant_detail'
match '/participants/:id' => 'api_music_sessions#participant_delete', :via => :delete
match '/participants/:client_id' => 'api_music_sessions#participant_show', :via => :get, :as => 'api_session_participant_detail'
match '/participants/:client_id' => 'api_music_sessions#participant_delete', :via => :delete
match '/sessions/:id' => 'api_music_sessions#show', :via => :get, :as => 'api_session_detail'
match '/sessions/:id' => 'api_music_sessions#delete', :via => :delete
match '/sessions' => 'api_music_sessions#index', :via => :get

View File

@ -10,4 +10,8 @@ FactoryGirl.define do
end
end
factory :connection, :class => JamRuby::Connection do
end
end

View File

@ -23,7 +23,10 @@ describe "Music Session API ", :type => :api do
it "should create session" do
# create the session
post '/api/sessions.json', '{"description" : "a session"}', "CONTENT_TYPE" => 'application/json'
# create a client connection
client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "1")
post '/api/sessions.json', '{"description" : "a session", "client_id" : "' + client.client_id + '"}', "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(201)
# now fetch it's data
@ -44,7 +47,9 @@ describe "Music Session API ", :type => :api do
list.length.should == 0
# create the session
post '/api/sessions.json', '{"description" : "a session"}', "CONTENT_TYPE" => 'application/json'
client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "2")
post '/api/sessions.json', '{"description" : "a session", "client_id" : "' + client.client_id + '"}', "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(201)
# now fetch it's data
get last_response.headers["Location"]
@ -65,43 +70,33 @@ describe "Music Session API ", :type => :api do
it "should add/remove member from session" do
# create the session
post '/api/sessions.json', '{"description" : "a session"}', "CONTENT_TYPE" => 'application/json'
client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "3")
post '/api/sessions.json', '{"description" : "a session", "client_id" : "' + client.client_id + '"}', "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(201)
# now fetch it's data
get last_response.headers["Location"]
music_session = JSON.parse(last_response.body)
music_session["participants"].length.should == 0
# create a member
post "/api/sessions/#{music_session["id"]}/participants.json", '{ "ip_address" : "1.2.3.4", "client_id" : "1" }', "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(201)
musician = JSON.parse(last_response.body)
# re-fetch the session now that there is a musician
get "/api/sessions/#{music_session["id"]}.json"
music_session = JSON.parse(last_response.body)
# there should be one musician in the response
# and the creator should be in the session
music_session["participants"].length.should == 1
musician = music_session["participants"][0]
# and that musician should have the same IP address
musician["ip_address"].should == "1.2.3.4"
musician["ip_address"].should == "1.1.1.1"
# and that musician should have the same IP address
musician["client_id"].should == "1"
# and that musician should have the correct IP address
musician["client_id"].should == "3"
# now delete that musician
delete "/api/participants/#{musician["id"]}.json", '', "CONTENT_TYPE" => 'application/json'
delete "/api/participants/#{musician["client_id"]}.json", '', "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(204)
# re-fetch the session now that there is not a musician
# re-fetch the session now that there is not a musician;
# we auto-delete sessions when the last person leaves
get "/api/sessions/#{music_session["id"]}.json"
music_session = JSON.parse(last_response.body)
last_response.status.should eql(404)
# there should be no musicians in the response
music_session["participants"].length.should == 0
end