VRFS-758 join request notification logic

This commit is contained in:
Brian Smith 2013-10-16 03:23:43 -04:00
parent 17c7e73894
commit 6dd0df75d9
17 changed files with 394 additions and 71 deletions

View File

@ -74,7 +74,7 @@ message ClientMessage {
optional MusicianSessionFresh musician_session_fresh = 115;
optional MusicianSessionStale musician_session_stale = 116;
optional HeartbeatAck heartbeat_ack = 117;
optional JoinRequestAccepted join_request_accepted = 118;
optional JoinRequestApproved join_request_approved = 118;
optional JoinRequestRejected join_request_rejected = 119;
// Client-Session messages (to/from)
@ -199,20 +199,32 @@ message MusicianSessionStale {
message JoinRequest {
optional string join_request_id = 1;
optional string username = 2;
optional string text = 3;
optional string session_id = 2;
optional string username = 3;
optional string photo_url = 4;
optional string msg = 5;
optional string notification_id = 6;
optional string created_at = 7;
}
message JoinRequestAccepted {
message JoinRequestApproved {
optional string join_request_id = 1;
optional string username = 2;
optional string text = 3;
optional string session_id = 2;
optional string username = 3;
optional string photo_url = 4;
optional string msg = 5;
optional string notification_id = 6;
optional string created_at = 7;
}
message JoinRequestRejected {
optional string join_request_id = 1;
optional string username = 2;
optional string text = 3;
optional string session_id = 2;
optional string username = 3;
optional string photo_url = 4;
optional string msg = 5;
optional string notification_id = 6;
optional string created_at = 7;
}
// route_to: session

View File

@ -124,11 +124,22 @@
return Jampb::ClientMessage.new(:type => ClientMessage::Type::MUSICIAN_SESSION_STALE, :route_to => CLIENT_TARGET, :musician_session_stale => stale)
end
# create a join request session message
def join_request(join_request_id, session_id, username, photo_url, msg, notification_id, created_at)
req = Jampb::JoinRequest.new(:join_request_id => join_request_id, :session_id => session_id, :username => username, :photo_url => photo_url, :msg => msg, :notification_id => notification_id, :created_at => created_at)
return Jampb::ClientMessage.new(:type => ClientMessage::Type::JOIN_REQUEST, :route_to => SESSION_TARGET_PREFIX + session_id, :join_request => req)
end
# create a user-joined session message
def join_request(session_id, join_request_id, username, text)
join_request = Jampb::JoinRequest.new(:join_request_id => join_request_id, :username => username, :text => text)
return Jampb::ClientMessage.new(:type => ClientMessage::Type::JOIN_REQUEST, :route_to => SESSION_TARGET_PREFIX + session_id, :join_request => join_request)
# create a join request approved session message
def join_request_approved(join_request_id, session_id, username, photo_url, msg, notification_id, created_at)
req_approved = Jampb::JoinRequestApproved.new(:join_request_id => join_request_id, :session_id => session_id, :username => username, :photo_url => photo_url, :msg => msg, :notification_id => notification_id, :created_at => created_at)
return Jampb::ClientMessage.new(:type => ClientMessage::Type::JOIN_REQUEST_APPROVED, :route_to => SESSION_TARGET_PREFIX + session_id, :join_request_approved => req_approved)
end
# create a join request rejected session message
def join_request_rejected(join_request_id, session_id, username, photo_url, msg, notification_id, created_at)
req_rejected = Jampb::JoinRequestRejected.new(:join_request_id => join_request_id, :session_id => session_id, :username => username, :photo_url => photo_url, :msg => msg, :notification_id => notification_id, :created_at => created_at)
return Jampb::ClientMessage.new(:type => ClientMessage::Type::JOIN_REQUEST_REJECTED, :route_to => SESSION_TARGET_PREFIX + session_id, :join_request_rejected => req_rejected)
end
# create a test message to send in session

View File

@ -11,7 +11,7 @@ module JamRuby
validates :user, :presence => true
validates :music_session, :presence => true
validates :text, presence: false, no_profanity: true, length: {maximum: 140} # arbitrary decision of 140. the database is at 2000 max on this field
validates :text, no_profanity: true, length: {maximum: 140} # arbitrary decision of 140. the database is at 2000 max on this field
validates_uniqueness_of :user_id, :scope => :music_session_id

View File

@ -108,7 +108,7 @@ module JamRuby
return ids
end
def format_msg(description, user)
def format_msg(description, user = nil)
name = ""
unless user.nil?
name = user.name
@ -138,9 +138,16 @@ module JamRuby
when NotificationTypes::SESSION_INVITATION
return "#{name} has invited you to a session."
when NotificationTypes::JOIN_REQUEST
return "#{name} has requested to join your session."
when NotificationTypes::JOIN_REQUEST_APPROVED
return "#{name} has approved your request to join the session."
when NotificationTypes::JOIN_REQUEST_REJECTED
return "We're sorry, but you cannot join the session at this time."
# when "social_media_friend_joined"
# when "join_request_approved"
# when "join_request_rejected"
# when "band_invitation"
# when "band_invitation_accepted"
# when "recording_available"
@ -181,7 +188,7 @@ module JamRuby
notification.save
# (2) create notification
notification_msg = format_msg(NotificationTypes::FRIEND_REQUEST, user)
notification_msg = format_msg(notification.description, user)
msg = @@message_factory.friend_request(friend_request_id, user_id, user.name, user.photo_url, friend_id, notification_msg, notification.id, notification.created_at.to_s)
# (3) send notification
@ -200,7 +207,7 @@ module JamRuby
notification.save
# (2) create notification
notification_msg = format_msg(NotificationTypes::FRIEND_REQUEST_ACCEPTED, friend)
notification_msg = format_msg(notification.description, friend)
msg = @@message_factory.friend_request_accepted(friend_id, friend.name, friend.photo_url, user_id, notification_msg, notification.id, notification.created_at.to_s)
# (3) send notification
@ -231,7 +238,6 @@ module JamRuby
msg = @@message_factory.musician_session_join(music_session.id, user.id, user.name, user.photo_url)
# (2) send notification
puts "CONNECTION.CLIENT_ID=#{connection.client_id}"
@@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => connection.client_id})
end
@ -276,15 +282,58 @@ module JamRuby
end
end
def send_join_request(music_session, join_request, sender, text)
def send_join_request(music_session, join_request, text)
# (1) save to database
notification = Notification.new
notification.description = NotificationTypes::JOIN_REQUEST
notification.source_user_id = join_request.user.id
notification.target_user_id = music_session.creator.id
notification.session_id = music_session.id
notification.save
# (2) create notification
msg = @@message_factory.join_request(music_session.id, join_request.id, sender.name, text)
notification_msg = format_msg(notification.description, join_request.user)
msg = @@message_factory.join_request(join_request.id, music_session.id, join_request.user.name, join_request.user.photo_url, notification_msg, notification.id, notification.created_at.to_s)
# (3) send notification
@@mq_router.server_publish_to_session(music_session, msg)
@@mq_router.publish_to_user(music_session.creator.id, msg)
end
def send_join_request_approved(music_session, join_request)
# (1) save to database
notification = Notification.new
notification.description = NotificationTypes::JOIN_REQUEST_APPROVED
notification.source_user_id = music_session.creator.id
notification.target_user_id = join_request.user.id
notification.session_id = music_session.id
notification.save
# (2) create notification
notification_msg = format_msg(notification.description, music_session.creator.name)
msg = @@message_factory.join_request_approved(join_request.id, music_session.id, music_session.creator.name, music_session.creator.photo_url, notification_msg, notification.id, notification.created_at.to_s)
# (3) send notification
@@mq_router.publish_to_user(join_request.user.id, msg)
end
def send_join_request_rejected(music_session, join_request)
# (1) save to database
notification = Notification.new
notification.description = NotificationTypes::JOIN_REQUEST_REJECTED
notification.source_user_id = music_session.creator.id
notification.target_user_id = join_request.user.id
notification.session_id = music_session.id
notification.save
# (2) create notification
notification_msg = format_msg(notification.description, music_session.creator.name)
msg = @@message_factory.join_request_rejected(join_request.id, music_session.id, music_session.creator.name, music_session.creator.photo_url, notification_msg, notification.id, notification.created_at.to_s)
# (3) send notification
@@mq_router.publish_to_user(join_request.user.id, msg)
end
end

View File

@ -22,6 +22,8 @@
FRIEND_UPDATE : "FRIEND_UPDATE",
SESSION_INVITATION : "SESSION_INVITATION",
JOIN_REQUEST : "JOIN_REQUEST",
JOIN_REQUEST_APPROVED : "JOIN_REQUEST_APPROVED",
JOIN_REQUEST_REJECTED : "JOIN_REQUEST_REJECTED",
FRIEND_REQUEST : "FRIEND_REQUEST",
FRIEND_REQUEST_ACCEPTED : "FRIEND_REQUEST_ACCEPTED",
TEST_SESSION_MESSAGE : "TEST_SESSION_MESSAGE",

View File

@ -0,0 +1,29 @@
(function(context,$) {
"use strict";
context.JK = context.JK || {};
context.JK.AlertDialog = function(app, okButtonText, message, sessionId, callback) {
var logger = context.JK.logger;
function events() {
$('#btn-alert-ok').click(function(evt) {
callback(sessionId);
});
$('#btn-alert-cancel').click(function(evt) {
app.layout.closeDialog('alert');
});
}
function initialize() {
events();
$('#btn-alert-ok').text(okButtonText);
$('#alert-message').html(message);
}
this.initialize = initialize;
};
})(window,jQuery);

View File

@ -12,6 +12,28 @@
var self = this;
var logger = context.JK.logger;
function createJoinRequest(joinRequest) {
return $.ajax({
type: "POST",
dataType: "json",
url: '/api/join_requests',
contentType: 'application/json',
processData: false,
data: JSON.stringify(joinRequest)
});
}
function updateJoinRequest(joinRequestId, isApproved) {
return $.ajax({
type: "PUT",
dataType: "json",
url: '/api/join_requests/' + joinRequestId,
contentType: 'application/json',
processData: false,
data: JSON.stringify({"approved": isApproved})
});
}
function updateSession(id, newSession, onSuccess) {
logger.debug('Rest.updateSession');
return $.ajax('/api/sessions/' + id, {
@ -297,6 +319,8 @@
this.userDownloadedClient = userDownloadedClient;
this.userCertifiedGear = userCertifiedGear;
this.userSocialPromoted = userSocialPromoted;
this.createJoinRequest = createJoinRequest;
this.updateJoinRequest = updateJoinRequest;
return this;
};

View File

@ -621,6 +621,20 @@
$('#cancel-button', $notify).html("CANCEL");
}
}
if (descriptor.cancel_callback !== undefined) {
$('#cancel-button', $notify).click(function() {
if (descriptor.cancel_callback_args) {
logger.debug("descriptor.cancel_callback_args=" + descriptor.cancel_callback_args);
descriptor.cancel_callback(descriptor.cancel_callback_args);
return false;
}
else {
descriptor.cancel_callback();
return false;
}
});
}
}
else {
$('#ok-button', $notify).html("OKAY");

View File

@ -6,6 +6,9 @@
context.JK.SessionList = function(app) {
var logger = context.JK.logger;
var termsDialog;
var alertDialog;
var rest = context.JK.Rest();
var LATENCY = {
GOOD : {description: "GOOD", style: "latency-green", min: 0.0, max: 20.0},
MEDIUM : {description: "MEDIUM", style: "latency-yellow", min: 20.0, max: 40.0},
@ -135,12 +138,41 @@
// wire up the Join Link to the T&Cs dialog
var $parentRow = $('tr[id=' + session.id + ']', tbGroup);
$('#join-link', $parentRow).click(function(evt) {
openTerms(session.id);
});
if (session.approval_required) {
$('#join-link', $parentRow).click(function(evt) {
openAlert(session.id);
});
}
else {
$('#join-link', $parentRow).click(function(evt) {
openTerms(session.id);
});
}
}
}
function openAlert(sessionId) {
alertDialog = new context.JK.AlertDialog(app, "YES",
"You must be approved to join this session. Would you like to send a request to join?",
sessionId, onCreateJoinRequest);
alertDialog.initialize();
app.layout.showDialog('alert');
}
function onCreateJoinRequest(sessionId) {
var joinRequest = {};
joinRequest.music_session = sessionId;
joinRequest.user = context.JK.currentUserId;
rest.createJoinRequest(joinRequest)
.done(function(response) {
}).error(app.ajaxError);
app.layout.closeDialog('alert');
}
function openTerms(sessionId) {
termsDialog = new context.JK.TermsDialog(app, sessionId, onTermsAccepted);
termsDialog.initialize();

View File

@ -147,6 +147,8 @@
// wire up "x" button to delete notification
$notification.find('#img-delete-notification').click(deleteNotificationHandler);
// customize action buttons based on notification type
if (type === context.JK.MessageType.FRIEND_REQUEST) {
var $action_btn = $notification.find('#btn-notification-action');
$action_btn.text('ACCEPT');
@ -161,9 +163,26 @@
var $action_btn = $notification.find('#btn-notification-action');
$action_btn.text('JOIN');
$action_btn.click(function() {
joinSession({ "session_id": payload.session_id, "notification_id": payload.notification_id });
openTerms({ "session_id": payload.session_id, "notification_id": payload.notification_id });
});
}
else if (type === context.JK.MessageType.JOIN_REQUEST) {
var $action_btn = $notification.find('#btn-notification-action');
$action_btn.text('APPROVE');
$action_btn.click(function() {
approveJoinRequest({ "join_request_id": payload.join_request_id, "notification_id": payload.notification_id });
});
}
else if (type === context.JK.MessageType.JOIN_REQUEST_APPROVED) {
var $action_btn = $notification.find('#btn-notification-action');
$action_btn.text('JOIN');
$action_btn.click(function() {
openTerms({ "session_id": payload.session_id, "notification_id": payload.notification_id });
});
}
else if (type === context.JK.MessageType.JOIN_REQUEST_REJECTED) {
$notification.find('#div-actions').hide();
}
}
function deleteNotificationHandler(evt) {
@ -314,22 +333,6 @@
}
}
function acceptFriendRequest(args) {
rest.acceptFriendRequest({
status : 'accept',
friend_request_id : args.friend_request_id
}).done(function(response) {
deleteNotification(args.notification_id); // delete notification corresponding to this friend request
initializeFriendsPanel(); // refresh friends panel when request is accepted
}).error(app.ajaxError);
}
function joinSession(args) {
context.location = "#/session/" + args.session_id;
deleteNotification(args.notification_id);
}
// default handler for incoming notification
function handleNotification(payload, type) {
var sidebarText;
@ -406,11 +409,28 @@
$('.sidebar .invite-friend-row').hoverIntent(inviteHoverIn, inviteHoverOut);
// $('#sidebar-div').mouseleave(function(evt) {
// hideSearchResults();
// });
registerFriendUpdate();
registerFriendRequest();
registerFriendRequestAccepted();
registerMusicianSessionJoin();
registerMusicianSessionDepart();
registerFriendSessionJoin();
registerSessionInvitation();
registerJoinRequest();
registerJoinRequestApproved();
registerJoinRequestRejected();
// wire up FRIEND_UPDATE handler
// watch for Invite More Users events
$('#sidebar-div .btn-email-invitation').click(function() {
invitationDialog.showEmailDialog();
});
$('#sidebar-div .btn-gmail-invitation').click(function() {
invitationDialog.showGoogleDialog();
});
}
function registerFriendUpdate() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_UPDATE, function(header, payload) {
logger.debug("Handling FRIEND_UPDATE msg " + JSON.stringify(payload));
@ -426,9 +446,9 @@
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
});
});
//////////////////////////////////////////////////////////////
}
// wire up FRIEND_REQUEST handler
function registerFriendRequest() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_REQUEST, function(header, payload) {
logger.debug("Handling FRIEND_REQUEST msg " + JSON.stringify(payload));
@ -447,9 +467,20 @@
}
);
});
//////////////////////////////////////////////////////////////
}
// wire up FRIEND_REQUEST_ACCEPTED handler
function acceptFriendRequest(args) {
rest.acceptFriendRequest({
status : 'accept',
friend_request_id : args.friend_request_id
}).done(function(response) {
deleteNotification(args.notification_id); // delete notification corresponding to this friend request
initializeFriendsPanel(); // refresh friends panel when request is accepted
}).error(app.ajaxError);
}
function registerFriendRequestAccepted() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_REQUEST_ACCEPTED, function(header, payload) {
logger.debug("Handling FRIEND_REQUEST_ACCEPTED msg " + JSON.stringify(payload));
@ -465,9 +496,9 @@
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
});
});
//////////////////////////////////////////////////////////////
}
// wire up MUSICIAN_SESSION_JOIN handler
function registerMusicianSessionJoin() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, function(header, payload) {
logger.debug("Handling MUSICIAN_SESSION_JOIN msg " + JSON.stringify(payload));
@ -478,9 +509,9 @@
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
});
});
//////////////////////////////////////////////////////////////
}
// wire up MUSICIAN_SESSION_DEPART handler
function registerMusicianSessionDepart() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_DEPART, function(header, payload) {
logger.debug("Handling MUSICIAN_SESSION_DEPART msg " + JSON.stringify(payload));
@ -491,9 +522,9 @@
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
});
});
//////////////////////////////////////////////////////////////
}
// wire up MUSICIAN_SESSION_DEPART handler
function registerFriendSessionJoin() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_SESSION_JOIN, function(header, payload) {
logger.debug("Handling FRIEND_SESSION_JOIN msg " + JSON.stringify(payload));
@ -504,9 +535,9 @@
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
});
});
//////////////////////////////////////////////////////////////
}
// wire up SESSION_INVITATION handler
function registerSessionInvitation() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_INVITATION, function(header, payload) {
logger.debug("Handling SESSION_INVITATION msg " + JSON.stringify(payload));
@ -538,20 +569,97 @@
},
{
"ok_text": "JOIN SESSION",
"ok_callback": joinSession,
"ok_callback": openTerms,
"ok_callback_args": { "session_id": payload.session_id, "notification_id": payload.notification_id }
}
);
});
//////////////////////////////////////////////////////////////
}
// watch for Invite More Users events
$('#sidebar-div .btn-email-invitation').click(function() {
invitationDialog.showEmailDialog();
function openTerms(args) {
var termsDialog = new context.JK.TermsDialog(app, args, onTermsAccepted);
termsDialog.initialize();
app.layout.showDialog('terms');
}
function onTermsAccepted(args) {
deleteNotification(args.notification_id);
context.location = '#/session/' + args.session_id;
}
function registerJoinRequest() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST, function(header, payload) {
logger.debug("Handling JOIN_REQUEST msg " + JSON.stringify(payload));
handleNotification(payload, header.type);
// display notification
app.notify({
"title": "New Join Request",
"text": payload.msg,
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
},
{
"ok_text": "APPROVE",
"ok_callback": approveJoinRequest,
"ok_callback_args": { "join_request_id": payload.join_request_id, "notification_id": payload.notification_id }
},
{
"cancel_text": "REJECT",
"cancel_callback": rejectJoinRequest,
"cancel_callback_args": { "join_request_id": payload.join_request_id, "notification_id": payload.notification_id }
}
);
});
}
$('#sidebar-div .btn-gmail-invitation').click(function() {
invitationDialog.showGoogleDialog();
function approveJoinRequest(args) {
rest.updateJoinRequest(args.join_request_id, true)
.done(function(response) {
deleteNotification(args.notification_id);
}).error(app.ajaxError);
}
function rejectJoinRequest(args) {
rest.updateJoinRequest(args.join_request_id, false)
.done(function(response) {
deleteNotification(args.notification_id);
}).error(app.ajaxError);
}
function registerJoinRequestApproved() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST_APPROVED, function(header, payload) {
logger.debug("Handling JOIN_REQUEST_APPROVED msg " + JSON.stringify(payload));
handleNotification(payload, header.type);
// display notification
app.notify({
"title": "Join Request Approved",
"text": payload.msg,
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
},
{
"ok_text": "JOIN SESSION",
"ok_callback": openTerms,
"ok_callback_args": { "session_id": payload.session_id, "notification_id": payload.notification_id }
}
);
});
}
function registerJoinRequestRejected() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST_REJECTED, function(header, payload) {
logger.debug("Handling JOIN_REQUEST_REJECTED msg " + JSON.stringify(payload));
handleNotification(payload, header.type);
// display notification
app.notify({
"title": "Join Request Rejected",
"text": payload.msg,
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
});
});
}

View File

@ -3,13 +3,13 @@
"use strict";
context.JK = context.JK || {};
context.JK.TermsDialog = function(app, sessionId, callback) {
context.JK.TermsDialog = function(app, args, callback) {
var logger = context.JK.logger;
function events() {
$('#btn-accept-terms').click(function(evt) {
callback(sessionId);
callback(args);
});
$('#btn-cancel-terms').click(function(evt) {

View File

@ -27,14 +27,33 @@ class ApiJoinRequestsController < ApiController
if @join_request.errors.any?
response.status = :unprocessable_entity
respond_with @join_request
respond_with "You cannot join the session at this time."
# respond_with @join_request
else
# send notification
Notification.send_join_request(music_session, @join_request, sender, text)
Notification.send_join_request(music_session, @join_request, text)
respond_with @join_request, :responder => ApiResponder, :location => api_join_request_detail_url(@join_request)
end
end
def update
@join_request = JoinRequest.find(params[:id])
if params[:approved]
# generate invitation if join request is approved
invitation = Invitation.new
invitation.sender = current_user
invitation.receiver = @join_request.user
invitation.music_session = @join_request.music_session
invitation.join_request = @join_request
invitation.save
Notification.send_join_request_approved(@join_request.music_session, @join_request)
else
Notification.send_join_request_rejected(@join_request.music_session, @join_request)
end
end
def delete
@join_request = JoinRequest.show(params[:id], current_user)
@join_request.delete

View File

@ -0,0 +1,3 @@
object @join_request
extends "api_join_requests/join_request"

View File

@ -0,0 +1,18 @@
<!-- Alert Dialog -->
<div class="dialog" layout="dialog" layout-id="alert" style="max-width:550px;">
<div class="content-head">
<%= image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' } %>
<h1>Terms and Conditions</h1>
</div>
<div class="dialog-inner">
<span id="alert-message"></span>
<br clear="left" /><br />
<div class="left">
<a id="btn-alert-cancel" layout-action="close" class="button-orange">CANCEL</a>
</div>
<div class="right">
<a id="btn-alert-ok" layout-action="close" class="button-orange"></a>
</div>
<br clear="all" />
</div>
</div>

View File

@ -7,9 +7,9 @@
<p></p>
<div class="detail"></div>
<div class="right clearall">
<a id="cancel-button" href="#" class="button-grey" layout-action="close">CANCEL</a>
&nbsp;&nbsp;
<a id="ok-button" href="#" class="button-orange" layout-action="close">OKAY</a>
&nbsp;&nbsp;
<a id="cancel-button" href="#" class="button-grey" layout-action="close">CANCEL</a>
</div>
</div>

View File

@ -14,6 +14,7 @@
<%= render "vu_meters" %>
<%= render "ftue" %>
<%= render "terms" %>
<%= render "alert" %>
<%= render "sidebar" %>
<%= render "createSession" %>
<%= render "findSession" %>

View File

@ -240,6 +240,7 @@ SampleApp::Application.routes.draw do
match '/join_requests/:id' => 'api_join_requests#show', :via => :get, :as => 'api_join_request_detail'
match '/join_requests/:id' => 'api_join_requests#delete', :via => :delete
match '/join_requests' => 'api_join_requests#create', :via => :post
match '/join_requests/:id' => 'api_join_requests#update', :via => :put
match '/join_requests' => 'api_join_requests#index', :via => :get
# Location lookups