From 7ec4d6021d1844692a132a8c0859215b5dc91fb3 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sun, 31 Mar 2013 14:07:46 -0400 Subject: [PATCH 1/9] VRFS-282 VRFS-283 toasts / notifications for friend updates and requests --- lib/jam_ruby/message_factory.rb | 19 ++--- lib/jam_ruby/models/friend_request.rb | 4 +- lib/jam_ruby/models/notification.rb | 99 ++++++++++++++++++++++----- lib/jam_ruby/models/user.rb | 4 ++ lib/jam_ruby/mq_router.rb | 6 -- 5 files changed, 96 insertions(+), 36 deletions(-) diff --git a/lib/jam_ruby/message_factory.rb b/lib/jam_ruby/message_factory.rb index fab86c1b9..ca3b7cc0d 100644 --- a/lib/jam_ruby/message_factory.rb +++ b/lib/jam_ruby/message_factory.rb @@ -111,23 +111,24 @@ return Jampb::ClientMessage.new(:type => ClientMessage::Type::SESSION_INVITATION, :route_to => USER_TARGET_PREFIX + receiver_id, :session_invitation => session_invitation) end + # create a friend update message + def friend_update(user_id, name, photo_url, online, msg) + friend = Jampb::FriendUpdate.new(:user_id => user_id, :name => name, :photo_url => photo_url, :online => online, :msg => msg) + return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_UPDATE, :route_to => USER_TARGET_PREFIX + user_id, :friend_update => friend) + end + # create a friend request message - def friend_request(user_id, name, photo_url, friend_id) - friend_request = Jampb::FriendRequest.new(:user_id => user_id, :name => name, :photo_url => photo_url, :friend_id => friend_id) + def friend_request(id, user_id, name, photo_url, friend_id, msg) + friend_request = Jampb::FriendRequest.new(:id => id, :user_id => user_id, :name => name, :photo_url => photo_url, :friend_id => friend_id, :msg => msg) return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_REQUEST, :route_to => USER_TARGET_PREFIX + friend_id, :friend_request => friend_request) end # create a friend request acceptance message - def friend_request_accepted(friend_id, name, photo_url, user_id) - friend_request_accepted = Jampb::FriendRequestAccepted.new(:friend_id => friend_id, :name => name, :photo_url => photo_url, :user_id => user_id) + def friend_request_accepted(friend_id, name, photo_url, user_id, msg) + friend_request_accepted = Jampb::FriendRequestAccepted.new(:friend_id => friend_id, :name => name, :photo_url => photo_url, :user_id => user_id, :msg => msg) return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_REQUEST_ACCEPTED, :route_to => USER_TARGET_PREFIX + user_id, :friend_request_accepted => friend_request_accepted) end - # create a friend update message - def friend_update(user_id, online) - friend = Jampb::FriendUpdate.new(:user_id => user_id, :online => online) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_UPDATE, :route_to => USER_TARGET_PREFIX + user_id, :friend_update => friend) - end ############## P2P CLIENT MESSAGES ################# # send a request to do a ping diff --git a/lib/jam_ruby/models/friend_request.rb b/lib/jam_ruby/models/friend_request.rb index a221402ef..616319076 100644 --- a/lib/jam_ruby/models/friend_request.rb +++ b/lib/jam_ruby/models/friend_request.rb @@ -27,7 +27,7 @@ module JamRuby friend_request.save # send notification - # Notification.send_friend_request(user_id, friend_id) + Notification.send_friend_request(friend_request.id, user_id, friend_id) else ActiveRecord::Base.transaction do @@ -41,7 +41,7 @@ module JamRuby Friendship.save(friend_request.user_id, friend_request.friend_id) # send notification - # Notification.send_friend_request_accepted(user_id, friend_id) + Notification.send_friend_request_accepted(user_id, friend_id) end end end diff --git a/lib/jam_ruby/models/notification.rb b/lib/jam_ruby/models/notification.rb index 1247146ec..32f4871e2 100644 --- a/lib/jam_ruby/models/notification.rb +++ b/lib/jam_ruby/models/notification.rb @@ -1,6 +1,43 @@ module JamRuby class Notification < ActiveRecord::Base + def index(user_id) + results = Notification.where(:target_user_id => user_id).limit(50) + return results + end + + def formatted_msg + target_user, source_user, band, session, recording, invitation, join_request = nil + + unless self.target_user_id.nil? + target_user = User.find(self.target_user_id) + end + + unless self.source_user_id.nil? + source_user = User.find(self.source_user_id) + end + + unless self.band_id.nil? + band = Band.find(self.band_id) + end + + unless self.session_id.nil? + session = MusicSession.find(self.session_id) + end + + unless self.recording_id.nil? + recording = Recording.find(self.recording_id) + end + + unless self.invitation_id.nil? + invitation = Invitation.find(self.invitation_id) + end + + unless self.join_request_id.nil? + join_request = JoinRequest.find(self.join_request_id) + end + end + # TODO: MAKE ALL METHODS BELOW ASYNC SO THE CLIENT DOESN'T BLOCK ON NOTIFICATION LOGIC # TODO: ADD TESTS FOR THIS CLASS @@ -9,9 +46,8 @@ module JamRuby @@mq_router = MQRouter.new @@message_factory = MessageFactory.new - def index(user_id) - results = Notification.where(:user_id => user_id).limit(50) - return results + def delete_all(session_id) + Notification.delete_all "(session_id = '#{session_id}')" end ################### HELPERS ################### @@ -41,10 +77,37 @@ module JamRuby return ids end + def format_msg(type, user) + case type + when "friend_update" + return "#{user.name} is now " + + when "friend_request" + return "#{user.name} has sent you a friend request." + + when "friend_request_accepted" + return "#{user.name} has accepted your friend request." + + when "friend_joined_session" + when "social_media_friend_joined" + when "join_request_approved" + when "join_request_rejected" + when "session_invitation" + when "band_invitation" + when "band_invitation_accepted" + when "recording_available" + else + end + end + ################### FRIEND UPDATE ################### def send_friend_update(user_id, online, connection) + user = User.find(user_id) + # (1) create notification - msg = @@message_factory.friend_update(user_id, online) + online_msg = online ? "online." : "offline." + notification_msg = format_msg("friend_update", user) + online_msg + msg = @@message_factory.friend_update(user_id, user.name, user.photo_url, online, notification_msg) # (2) get all of this user's friends friend_ids = retrieve_friends(connection, user_id) @@ -54,21 +117,22 @@ module JamRuby end ################### FRIEND REQUEST ################### - def send_friend_request(user_id, friend_id) + def send_friend_request(id, user_id, friend_id) user = User.find(user_id) # (1) create notification - msg = @@message_factory.friend_request(user_id, user.name, user.photo_url, friend_id) + notification_msg = format_msg("friend_request", user) + msg = @@message_factory.friend_request(id, user_id, user.name, user.photo_url, friend_id, notification_msg) # (2) send notification @@mq_router.publish_to_user(friend_id, msg) # (3) save to database - # notification = Notification.new - # notification.type = "friend_request" - # notification.source_user_id = user_id - # notification.target_user_id = friend_id - # notification.save + notification = Notification.new + notification.type = "friend_request" + notification.source_user_id = user_id + notification.target_user_id = friend_id + notification.save end ############### FRIEND REQUEST ACCEPTED ############### @@ -82,11 +146,11 @@ module JamRuby @@mq_router.publish_to_user(user_id, msg) # (3) save to database - # notification = Notification.new - # notification.type = "friend_request_accepted" - # notification.source_user_id = friend_id - # notification.target_user_id = user_id - # notification.save + notification = Notification.new + notification.type = "friend_request_accepted" + notification.source_user_id = friend_id + notification.target_user_id = user_id + notification.save end ################## SESSION INVITATION ################## @@ -137,9 +201,6 @@ module JamRuby # (3) save to database end - - # TODO: add methods to delete Notifications based on user id, session id, etc. - end end end \ No newline at end of file diff --git a/lib/jam_ruby/models/user.rb b/lib/jam_ruby/models/user.rb index ff3860cd1..ba4b3e8a9 100644 --- a/lib/jam_ruby/models/user.rb +++ b/lib/jam_ruby/models/user.rb @@ -61,6 +61,10 @@ module JamRuby has_many :favorites, :class_name => "JamRuby::UserFavorite", :foreign_key => "user_id" has_many :inverse_favorites, :through => :favorites, :class_name => "JamRuby::User" + # notifications + has_many :notifications, :class_name => "JamRuby::Notification", :foreign_key => "target_user_id" + has_many :inverse_notifications, :through => :notifications, :class_name => "JamRuby::User" + # friends has_many :friendships, :class_name => "JamRuby::Friendship", :foreign_key => "user_id" has_many :friends, :through => :friendships, :class_name => "JamRuby::User" diff --git a/lib/jam_ruby/mq_router.rb b/lib/jam_ruby/mq_router.rb index 2aec9a117..8fb3b30a6 100644 --- a/lib/jam_ruby/mq_router.rb +++ b/lib/jam_ruby/mq_router.rb @@ -11,9 +11,7 @@ class MQRouter @@log = Logging.logger[MQRouter] end - def access_music_session(music_session, user) - if music_session.nil? raise ArgumentError, 'specified session not found' end @@ -50,7 +48,6 @@ class MQRouter # sends a message to a client with no checking of permissions (RAW USAGE) # this method deliberately has no database interactivity/active_record objects def publish_to_client(client_id, client_msg, sender = {:client_id => ""}) - EM.schedule do sender_client_id = sender[:client_id] @@ -64,7 +61,6 @@ class MQRouter # sends a message to a session with no checking of permissions (RAW USAGE) # this method deliberately has no database interactivity/active_record objects def publish_to_session(music_session_id, client_ids, client_msg, sender = {:client_id => ""}) - EM.schedule do sender_client_id = sender[:client_id] @@ -81,7 +77,6 @@ class MQRouter # sends a message to a user with no checking of permissions (RAW USAGE) # this method deliberately has no database interactivity/active_record objects def publish_to_user(user_id, user_msg) - EM.schedule do @@log.debug "publishing to user:#{user_id} from server" # put it on the topic exchange for users @@ -92,7 +87,6 @@ class MQRouter # sends a message to a list of friends with no checking of permissions (RAW USAGE) # this method deliberately has no database interactivity/active_record objects def publish_to_friends(friend_ids, user_msg, from_user_id) - EM.schedule do friend_ids.each do |friend_id| @@log.debug "publishing to friend:#{friend_id} from user #{from_user_id}" From 28ecbdfa488ee3ec522d5e1e4596bfc7d6c146af Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sun, 31 Mar 2013 17:49:47 -0400 Subject: [PATCH 2/9] fix tests / move notification types to constants file --- lib/jam_ruby.rb | 3 +- lib/jam_ruby/constants/notification_types.rb | 7 ++++ lib/jam_ruby/models/friend_request.rb | 2 +- lib/jam_ruby/models/notification.rb | 35 +++++++++++--------- 4 files changed, 29 insertions(+), 18 deletions(-) create mode 100644 lib/jam_ruby/constants/notification_types.rb diff --git a/lib/jam_ruby.rb b/lib/jam_ruby.rb index d7a668b29..2bcc3471e 100644 --- a/lib/jam_ruby.rb +++ b/lib/jam_ruby.rb @@ -10,8 +10,9 @@ require "will_paginate/active_record" require "action_mailer" require "devise" require "sendgrid" -require "jam_ruby/constants/validation_messages" require "jam_ruby/constants/limits" +require "jam_ruby/constants/notification_types" +require "jam_ruby/constants/validation_messages" require "jam_ruby/errors/permission_error" require "jam_ruby/errors/state_error" require "jam_ruby/errors/jam_argument_error" diff --git a/lib/jam_ruby/constants/notification_types.rb b/lib/jam_ruby/constants/notification_types.rb new file mode 100644 index 000000000..031409dc2 --- /dev/null +++ b/lib/jam_ruby/constants/notification_types.rb @@ -0,0 +1,7 @@ +module NotificationTypes + + FRIEND_UPDATE = "friend_update" + FRIEND_REQUEST = "friend_request" + FRIEND_REQUEST_ACCEPTED = "friend_request_accepted" + +end \ No newline at end of file diff --git a/lib/jam_ruby/models/friend_request.rb b/lib/jam_ruby/models/friend_request.rb index 616319076..348da4162 100644 --- a/lib/jam_ruby/models/friend_request.rb +++ b/lib/jam_ruby/models/friend_request.rb @@ -41,7 +41,7 @@ module JamRuby Friendship.save(friend_request.user_id, friend_request.friend_id) # send notification - Notification.send_friend_request_accepted(user_id, friend_id) + Notification.send_friend_request_accepted(friend_request.user_id, friend_request.friend_id) end end end diff --git a/lib/jam_ruby/models/notification.rb b/lib/jam_ruby/models/notification.rb index 32f4871e2..28abcddc4 100644 --- a/lib/jam_ruby/models/notification.rb +++ b/lib/jam_ruby/models/notification.rb @@ -79,24 +79,26 @@ module JamRuby def format_msg(type, user) case type - when "friend_update" + when NotificationTypes::FRIEND_UPDATE return "#{user.name} is now " - when "friend_request" + when NotificationTypes::FRIEND_REQUEST return "#{user.name} has sent you a friend request." - when "friend_request_accepted" + when NotificationTypes::FRIEND_REQUEST_ACCEPTED return "#{user.name} has accepted your friend request." - when "friend_joined_session" - when "social_media_friend_joined" - when "join_request_approved" - when "join_request_rejected" - when "session_invitation" - when "band_invitation" - when "band_invitation_accepted" - when "recording_available" else + return "" + # when "friend_joined_session" + # when "social_media_friend_joined" + # when "join_request_approved" + # when "join_request_rejected" + # when "session_invitation" + # when "band_invitation" + # when "band_invitation_accepted" + # when "recording_available" + # else end end @@ -106,7 +108,7 @@ module JamRuby # (1) create notification online_msg = online ? "online." : "offline." - notification_msg = format_msg("friend_update", user) + online_msg + notification_msg = format_msg(NotificationTypes::FRIEND_UPDATE, user) + online_msg msg = @@message_factory.friend_update(user_id, user.name, user.photo_url, online, notification_msg) # (2) get all of this user's friends @@ -121,7 +123,7 @@ module JamRuby user = User.find(user_id) # (1) create notification - notification_msg = format_msg("friend_request", user) + notification_msg = format_msg(NotificationTypes::FRIEND_REQUEST, user) msg = @@message_factory.friend_request(id, user_id, user.name, user.photo_url, friend_id, notification_msg) # (2) send notification @@ -129,7 +131,7 @@ module JamRuby # (3) save to database notification = Notification.new - notification.type = "friend_request" + notification.type = NotificationTypes::FRIEND_REQUEST notification.source_user_id = user_id notification.target_user_id = friend_id notification.save @@ -140,14 +142,15 @@ module JamRuby friend = User.find(friend_id) # (1) create notification - msg = @@message_factory.friend_request_accepted(friend_id, friend.name, friend.photo_url, user_id) + notification_msg = format_msg(NotificationTypes::FRIEND_REQUEST_ACCEPTED, friend) + msg = @@message_factory.friend_request_accepted(friend_id, friend.name, friend.photo_url, user_id, notification_msg) # (2) send notification @@mq_router.publish_to_user(user_id, msg) # (3) save to database notification = Notification.new - notification.type = "friend_request_accepted" + notification.type = NotificationTypes::FRIEND_REQUEST_ACCEPTED notification.source_user_id = friend_id notification.target_user_id = user_id notification.save From e53f71277974fda2fda00af9f47743e34077ad90 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Thu, 4 Apr 2013 13:12:06 -0400 Subject: [PATCH 3/9] VRFS-282 changes to support real-time notification updates in sidebar --- lib/jam_ruby/message_factory.rb | 18 ++-- lib/jam_ruby/models/musician_instrument.rb | 1 - lib/jam_ruby/models/notification.rb | 95 +++++++++++++--------- 3 files changed, 68 insertions(+), 46 deletions(-) diff --git a/lib/jam_ruby/message_factory.rb b/lib/jam_ruby/message_factory.rb index ca3b7cc0d..5d8729023 100644 --- a/lib/jam_ruby/message_factory.rb +++ b/lib/jam_ruby/message_factory.rb @@ -106,8 +106,8 @@ return Jampb::ClientMessage.new(:type => ClientMessage::Type::TEST_SESSION_MESSAGE, :route_to => SESSION_TARGET_PREFIX + session_id, :test_session_message => test) end - def session_invitation(receiver_id, invitation_id) - session_invitation = Jampb::SessionInvitation.new(:invitation => invitation_id) + def session_invitation(receiver_id, invitation_id, notification_id) + session_invitation = Jampb::SessionInvitation.new(:invitation => invitation_id, :notification_id => notification_id) return Jampb::ClientMessage.new(:type => ClientMessage::Type::SESSION_INVITATION, :route_to => USER_TARGET_PREFIX + receiver_id, :session_invitation => session_invitation) end @@ -118,14 +118,20 @@ end # create a friend request message - def friend_request(id, user_id, name, photo_url, friend_id, msg) - friend_request = Jampb::FriendRequest.new(:id => id, :user_id => user_id, :name => name, :photo_url => photo_url, :friend_id => friend_id, :msg => msg) + def friend_request(id, user_id, name, photo_url, friend_id, msg, notification_id, created_at) + friend_request = Jampb::FriendRequest.new(:id => id, + :user_id => user_id, :name => name, :photo_url => photo_url, :friend_id => friend_id, :msg => msg, + :notification_id => notification_id, :created_at => created_at) + return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_REQUEST, :route_to => USER_TARGET_PREFIX + friend_id, :friend_request => friend_request) end # create a friend request acceptance message - def friend_request_accepted(friend_id, name, photo_url, user_id, msg) - friend_request_accepted = Jampb::FriendRequestAccepted.new(:friend_id => friend_id, :name => name, :photo_url => photo_url, :user_id => user_id, :msg => msg) + def friend_request_accepted(friend_id, name, photo_url, user_id, msg, notification_id, created_at) + friend_request_accepted = Jampb::FriendRequestAccepted.new(:friend_id => friend_id, + :name => name, :photo_url => photo_url, :user_id => user_id, :msg => msg, + :notification_id => notification_id, :created_at => created_at) + return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_REQUEST_ACCEPTED, :route_to => USER_TARGET_PREFIX + user_id, :friend_request_accepted => friend_request_accepted) end diff --git a/lib/jam_ruby/models/musician_instrument.rb b/lib/jam_ruby/models/musician_instrument.rb index d8ef69378..503a4e6f3 100644 --- a/lib/jam_ruby/models/musician_instrument.rb +++ b/lib/jam_ruby/models/musician_instrument.rb @@ -14,6 +14,5 @@ module JamRuby def description @description = self.instrument.description end - end end \ No newline at end of file diff --git a/lib/jam_ruby/models/notification.rb b/lib/jam_ruby/models/notification.rb index 28abcddc4..8ad03142f 100644 --- a/lib/jam_ruby/models/notification.rb +++ b/lib/jam_ruby/models/notification.rb @@ -1,11 +1,26 @@ module JamRuby class Notification < ActiveRecord::Base + self.primary_key = 'id' + + default_scope order('created_at DESC') + + belongs_to :target_user, :class_name => "JamRuby::User", :foreign_key => "target_user_id" + belongs_to :source_user, :class_name => "JamRuby::User", :foreign_key => "source_user_id" + belongs_to :band, :class_name => "JamRuby::Band", :foreign_key => "band_id" + belongs_to :session, :class_name => "JamRuby::MusicSession", :foreign_key => "session_id" + belongs_to :recording, :class_name => "JamRuby::Recording", :foreign_key => "recording_id" + def index(user_id) results = Notification.where(:target_user_id => user_id).limit(50) return results end + def photo_url + self.source_user.photo_url + end + + # used for persisted notifications def formatted_msg target_user, source_user, band, session, recording, invitation, join_request = nil @@ -36,6 +51,8 @@ module JamRuby unless self.join_request_id.nil? join_request = JoinRequest.find(self.join_request_id) end + + return self.class.format_msg(self.description, source_user) end # TODO: MAKE ALL METHODS BELOW ASYNC SO THE CLIENT DOESN'T BLOCK ON NOTIFICATION LOGIC @@ -77,8 +94,8 @@ module JamRuby return ids end - def format_msg(type, user) - case type + def format_msg(description, user) + case description when NotificationTypes::FRIEND_UPDATE return "#{user.name} is now " @@ -122,53 +139,53 @@ module JamRuby def send_friend_request(id, user_id, friend_id) user = User.find(user_id) - # (1) create notification - notification_msg = format_msg(NotificationTypes::FRIEND_REQUEST, user) - msg = @@message_factory.friend_request(id, user_id, user.name, user.photo_url, friend_id, notification_msg) - - # (2) send notification - @@mq_router.publish_to_user(friend_id, msg) - - # (3) save to database + # (1) save to database notification = Notification.new - notification.type = NotificationTypes::FRIEND_REQUEST + notification.description = NotificationTypes::FRIEND_REQUEST notification.source_user_id = user_id notification.target_user_id = friend_id notification.save + + # (2) create notification + notification_msg = format_msg(NotificationTypes::FRIEND_REQUEST, user) + msg = @@message_factory.friend_request(id, user_id, user.name, user.photo_url, friend_id, notification_msg, notification.id, notification.created_at.to_s) + + # (3) send notification + @@mq_router.publish_to_user(friend_id, msg) end ############### FRIEND REQUEST ACCEPTED ############### def send_friend_request_accepted(user_id, friend_id) friend = User.find(friend_id) - # (1) create notification - notification_msg = format_msg(NotificationTypes::FRIEND_REQUEST_ACCEPTED, friend) - msg = @@message_factory.friend_request_accepted(friend_id, friend.name, friend.photo_url, user_id, notification_msg) - - # (2) send notification - @@mq_router.publish_to_user(user_id, msg) - - # (3) save to database + # (1) save to database notification = Notification.new - notification.type = NotificationTypes::FRIEND_REQUEST_ACCEPTED + notification.description = NotificationTypes::FRIEND_REQUEST_ACCEPTED notification.source_user_id = friend_id notification.target_user_id = user_id notification.save + + # (2) create notification + notification_msg = format_msg(NotificationTypes::FRIEND_REQUEST_ACCEPTED, 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 + @@mq_router.publish_to_user(user_id, msg) end ################## SESSION INVITATION ################## def send_session_invitation(receiver_id, invitation_id) - # (1) create notification - msg = @@message_factory.session_invitation(receiver_id, invitation_id) - - # (2) send notification - @@mq_router.publish_to_user(receiver_id, msg) + # (1) save to database + notification = Notification.new + notification.description = "session_invitation" + notification.target_user_id = receiver_id - # (3) save to database - # notification = Notification.new - # notification.type = "session_invitation" - # notification.target_user_id = receiver_id + # (2) create notification + msg = @@message_factory.session_invitation(receiver_id, invitation_id, notification.id) + + # (3) send notification + @@mq_router.publish_to_user(receiver_id, msg) end def send_session_left(music_session, connection, user) @@ -182,27 +199,27 @@ module JamRuby def send_join_request(music_session, join_request, sender, text) - # (1) create notification + # (1) save to database + # notification = Notification.new + + # (2) create notification msg = @@message_factory.join_request(music_session.id, join_request.id, sender.name, text) - # (2) send notification + # (3) send notification @@mq_router.server_publish_to_session(music_session, msg) - - # (3) save to database - # notification = Notification.new end def send_session_joined(connection, user) - # (1) create notification + # (1) save to database + + # (2) create notification msg = @@message_factory.user_joined_music_session(connection.music_session.id, user.id, user.name) - # (2a) send notification to session members + # (3a) send notification to session members @@mq_router.server_publish_to_session(connection.music_session, msg, sender = {:client_id => connection.client_id}) - # TODO: (2b) retrieve all friends and followers of user and send notification to them as well - - # (3) save to database + # TODO: (3b) retrieve all friends and followers of user and send notification to them as well end end end From c3824cac258b89b8534fd8f0669758722fe6394b Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Thu, 4 Apr 2013 23:57:16 -0400 Subject: [PATCH 4/9] VRFS-282 changes to support real-time notification updates in sidebar --- lib/jam_ruby/message_factory.rb | 6 +++--- lib/jam_ruby/models/notification.rb | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/jam_ruby/message_factory.rb b/lib/jam_ruby/message_factory.rb index 5d8729023..efcffd1aa 100644 --- a/lib/jam_ruby/message_factory.rb +++ b/lib/jam_ruby/message_factory.rb @@ -106,8 +106,8 @@ return Jampb::ClientMessage.new(:type => ClientMessage::Type::TEST_SESSION_MESSAGE, :route_to => SESSION_TARGET_PREFIX + session_id, :test_session_message => test) end - def session_invitation(receiver_id, invitation_id, notification_id) - session_invitation = Jampb::SessionInvitation.new(:invitation => invitation_id, :notification_id => notification_id) + def session_invitation(receiver_id, invitation_id) + session_invitation = Jampb::SessionInvitation.new(:invitation => invitation_id) return Jampb::ClientMessage.new(:type => ClientMessage::Type::SESSION_INVITATION, :route_to => USER_TARGET_PREFIX + receiver_id, :session_invitation => session_invitation) end @@ -131,7 +131,7 @@ friend_request_accepted = Jampb::FriendRequestAccepted.new(:friend_id => friend_id, :name => name, :photo_url => photo_url, :user_id => user_id, :msg => msg, :notification_id => notification_id, :created_at => created_at) - + return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_REQUEST_ACCEPTED, :route_to => USER_TARGET_PREFIX + user_id, :friend_request_accepted => friend_request_accepted) end diff --git a/lib/jam_ruby/models/notification.rb b/lib/jam_ruby/models/notification.rb index 8ad03142f..67b69cb2e 100644 --- a/lib/jam_ruby/models/notification.rb +++ b/lib/jam_ruby/models/notification.rb @@ -180,9 +180,10 @@ module JamRuby notification = Notification.new notification.description = "session_invitation" notification.target_user_id = receiver_id + notification.save # (2) create notification - msg = @@message_factory.session_invitation(receiver_id, invitation_id, notification.id) + msg = @@message_factory.session_invitation(receiver_id, invitation_id) # (3) send notification @@mq_router.publish_to_user(receiver_id, msg) From 23a0c16b7fff6df71b1d1a3e2c71c28b063847c6 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sat, 6 Apr 2013 21:43:00 -0400 Subject: [PATCH 5/9] add null check for source_user before returning photo_url --- lib/jam_ruby/models/notification.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/jam_ruby/models/notification.rb b/lib/jam_ruby/models/notification.rb index 67b69cb2e..561ccf058 100644 --- a/lib/jam_ruby/models/notification.rb +++ b/lib/jam_ruby/models/notification.rb @@ -17,7 +17,9 @@ module JamRuby end def photo_url - self.source_user.photo_url + unless self.source_user.nil? + self.source_user.photo_url + end end # used for persisted notifications From 8ca4848d28f3df9e6af0f280e62708b005d74783 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Wed, 10 Apr 2013 01:16:04 -0500 Subject: [PATCH 6/9] * updating ArtifactUpdate to reflect new mandatory fields --- Gemfile | 4 +++- lib/jam_ruby/models/artifact_update.rb | 17 +++++++++++++++-- spec/jam_ruby/models/artifact_update_spec.rb | 6 +++--- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index 75a43a941..7f01fde4b 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,8 @@ #ruby=1.9.3 source 'https://rubygems.org' -source 'https://jamjam:blueberryjam@www.jamkazam.com/gems/' +unless ENV["LOCAL_DEV"] == "1" + source 'https://jamjam:blueberryjam@www.jamkazam.com/gems/' +end # Look for $WORKSPACE, otherwise use "workspace" as dev path. workspace = ENV["WORKSPACE"] || "~/workspace" diff --git a/lib/jam_ruby/models/artifact_update.rb b/lib/jam_ruby/models/artifact_update.rb index 9367b25c3..d224f6120 100644 --- a/lib/jam_ruby/models/artifact_update.rb +++ b/lib/jam_ruby/models/artifact_update.rb @@ -7,12 +7,25 @@ module JamRuby self.primary_key = 'id' attr_accessible :version, :uri, :sha1, :environment, :product + + # ORDER MATTERS HERE- before_save for this method must be declared before mount_uploader: https://github.com/jnicklas/carrierwave/wiki/Known-Issues + before_save :update_uri_attributes mount_uploader :uri, ArtifactUploader validate :version, :presence => true validate :uri, :presence => true - validate :sha1, :presence => false - validate :environment, presence => true + validate :sha1, :presence => true + validate :size, :presence => true + validate :environment, :presence => true validate :product, :inclusion => {:in => PRODUCTS} + + private + + def update_uri_attributes + if uri.present? && uri_changed? + self.size = uri.file.size + self.sha1 = Digest::MD5.hexdigest(File.read(uri.current_path)) + end + end end end diff --git a/spec/jam_ruby/models/artifact_update_spec.rb b/spec/jam_ruby/models/artifact_update_spec.rb index c4ed36193..24075e310 100644 --- a/spec/jam_ruby/models/artifact_update_spec.rb +++ b/spec/jam_ruby/models/artifact_update_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'digest/md5' describe ArtifactUpdate do @@ -23,15 +24,14 @@ describe ArtifactUpdate do artifact.product = 'JamClient/Win32' artifact.version = '0.1.1' artifact.uri = File.open(ARTIFACT_FILE) - artifact.sha1 = 'blahablahblah' - artifact.save! artifact.environment.should == "public" artifact.product.should == "JamClient/Win32" artifact.version.should == "0.1.1" File.basename(artifact.uri.path).should == ARTIFACT_FILE - artifact.sha1.should == "blahablahblah" + artifact.sha1.should == Digest::MD5.hexdigest(File.read(ARTIFACT_FILE)) + artifact.size.should == File.size(ARTIFACT_FILE) found = ArtifactUpdate.find_by_product_and_version('JamClient/Win32', '0.1.1') artifact.should == found From 3abde183b745e45b14decf6c533ccf409c8dabc7 Mon Sep 17 00:00:00 2001 From: Mike Slemmer Date: Fri, 12 Apr 2013 15:36:05 -0700 Subject: [PATCH 7/9] added model stuff for mix --- lib/jam_ruby.rb | 1 + lib/jam_ruby/models/mix.rb | 51 +++++++++++++++++++++++++ spec/jam_ruby/models/mix_spec.rb | 64 ++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 lib/jam_ruby/models/mix.rb create mode 100644 spec/jam_ruby/models/mix_spec.rb diff --git a/lib/jam_ruby.rb b/lib/jam_ruby.rb index 2bcc3471e..6f9063e1b 100644 --- a/lib/jam_ruby.rb +++ b/lib/jam_ruby.rb @@ -58,6 +58,7 @@ require "jam_ruby/models/user_favorite" require "jam_ruby/models/search" require "jam_ruby/models/recording" require "jam_ruby/models/recorded_track" +require "jam_ruby/models/mix" include Jampb diff --git a/lib/jam_ruby/models/mix.rb b/lib/jam_ruby/models/mix.rb new file mode 100644 index 000000000..a05e4e23d --- /dev/null +++ b/lib/jam_ruby/models/mix.rb @@ -0,0 +1,51 @@ +# FIXME: +# Need to pass in the JSON spec for the mix and put that in the migration. + +module JamRuby + class Mix < ActiveRecord::Base + MAX_MIX_TIME = 7200 # 2 hours + + def self.schedule(recording_id, user_id, description, spec) + # This would have made it so you couldn't have more than one mix of a recording+owner + #raise unless self.where(:recording_id => recording_id, :owner_id => user_id).size == 0 + recording = Recording.find(recording_id) + raise if recording.nil? + raise if recording.owner_id != user_id + + mix = Mix.new + mix.recording_id = recording_id + mix.owner_id = user_id + mix.description = description + mix.spec = spec + mix.save + + mix + end + + def self.next(mix_server) + # First check if there are any mixes started so long ago that we want to re-run them + Mix.where("completed_at IS NULL AND started_at < ?", Time.now - MAX_MIX_TIME).each do |mix| + mix.started_at = nil + mix.mix_server = nil + mix.save + end + + mix = Mix.where(:started_at => nil).limit(1).first + return nil if mix.nil? + + mix.started_at = Time.now + mix.mix_server = mix_server + mix.save + + mix + end + + + def finish(url) + self.completed_at = Time.now + self.url = url + save + end + + end +end diff --git a/spec/jam_ruby/models/mix_spec.rb b/spec/jam_ruby/models/mix_spec.rb new file mode 100644 index 000000000..5e7753762 --- /dev/null +++ b/spec/jam_ruby/models/mix_spec.rb @@ -0,0 +1,64 @@ +require 'spec_helper' + +describe Mix do + before do + @user = FactoryGirl.create(:user) + @connection = FactoryGirl.create(:connection, :user => @user) + @instrument = FactoryGirl.create(:instrument, :description => 'a great instrument') + @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument) + @music_session = FactoryGirl.create(:music_session, :creator => @user, :musician_access => true) + @music_session.connections << @connection + @music_session.save + @recording = Recording.start(@music_session.id, @user) + @recording.stop + @mix = Mix.schedule(@recording.id, @user.id, "description", "{}") + end + + it "should create a mix for a user's recording properly" do + @mix.recording_id.should == @recording.id + @mix.owner_id.should == @user.id + @mix.description.should == "description" + @mix.spec.should == "{}" + @mix.url.should be_nil + @mix.mix_server.should be_nil + @mix.started_at.should be_nil + @mix.completed_at.should be_nil + end + + it "should fail to create a mix if the userid doesn't own the recording" do + @user2 = FactoryGirl.create(:user) + expect { Mix.schedule(@recording.id, @user2.id) }.to raise_error + end + + it "should fail if the recording doesn't exist" do + expect { @mix2 = Mix.schedule("bad_recording_id", @user.id) }.to raise_error + end + + it "should return a mix when the cron asks for it" do + this_mix = Mix.next("server") + this_mix.id.should == @mix.id + @mix.reload + @mix.started_at.should_not be_nil + @mix.mix_server.should == "server" + @mix.completed_at.should be_nil + end + + it "should record when a mix has finished" do + Mix.find(@mix.id).finish("http://blah") + @mix.reload + @mix.completed_at.should_not be_nil + @mix.url.should == "http://blah" + end + + it "should re-run a mix if it was started a long time ago" do + this_mix = Mix.next("server") + @mix.reload + @mix.started_at -= 1000000 + @mix.save + this_mix = Mix.next("server") + this_mix.id.should == @mix.id + end + +end + + From 7ba0317aebb7242d605b79c321d46d5f38619942 Mon Sep 17 00:00:00 2001 From: Mike Slemmer Date: Fri, 12 Apr 2013 17:16:40 -0700 Subject: [PATCH 8/9] return mixes with recordings --- lib/jam_ruby/models/mix.rb | 6 ++++++ lib/jam_ruby/models/recording.rb | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/jam_ruby/models/mix.rb b/lib/jam_ruby/models/mix.rb index a05e4e23d..9b9a4adac 100644 --- a/lib/jam_ruby/models/mix.rb +++ b/lib/jam_ruby/models/mix.rb @@ -5,6 +5,9 @@ module JamRuby class Mix < ActiveRecord::Base MAX_MIX_TIME = 7200 # 2 hours + self.primary_key = 'id' + belongs_to :recording, :class_name => "JamRuby::Recording", :inverse_of => :mix + def self.schedule(recording_id, user_id, description, spec) # This would have made it so you couldn't have more than one mix of a recording+owner #raise unless self.where(:recording_id => recording_id, :owner_id => user_id).size == 0 @@ -25,6 +28,7 @@ module JamRuby def self.next(mix_server) # First check if there are any mixes started so long ago that we want to re-run them Mix.where("completed_at IS NULL AND started_at < ?", Time.now - MAX_MIX_TIME).each do |mix| + # FIXME: This should probably throw some kind of log, since it means something went wrong mix.started_at = nil mix.mix_server = nil mix.save @@ -42,6 +46,8 @@ module JamRuby def finish(url) + raise if url.nil? + self.completed_at = Time.now self.url = url save diff --git a/lib/jam_ruby/models/recording.rb b/lib/jam_ruby/models/recording.rb index 3ea932606..07b88302b 100644 --- a/lib/jam_ruby/models/recording.rb +++ b/lib/jam_ruby/models/recording.rb @@ -7,6 +7,7 @@ module JamRuby belongs_to :owner, :class_name => "JamRuby::User", :inverse_of => :owned_recordings belongs_to :band, :class_name => "JamRuby::Band", :inverse_of => :recordings belongs_to :music_session, :class_name => "JamRuby::MusicSession", :inverse_of => :recording + has_one :mix, :class_name => "JamRuby::Mix", :inverse_of => :recording has_many :recorded_tracks, :class_name => "JamRuby::RecordedTrack", :foreign_key => :recording_id @@ -35,6 +36,14 @@ module JamRuby recordings_users.recording_id = recordings.id } ) + .joins( + %Q{ + LEFT OUTER JOIN + mixes + ON + recordings.id = mixes.recording_id + } + ) .order( %Q{ recordings.created_at DESC From 3700738b8470a891fb03a5dcf2b11d20503abe4a Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sat, 13 Apr 2013 22:58:31 -0400 Subject: [PATCH 9/9] VRFS-284 support for Accept Friend Request button in sidebar --- lib/jam_ruby/constants/notification_types.rb | 7 ++++--- lib/jam_ruby/message_factory.rb | 4 ++-- lib/jam_ruby/models/notification.rb | 7 ++++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/jam_ruby/constants/notification_types.rb b/lib/jam_ruby/constants/notification_types.rb index 031409dc2..07a68a62c 100644 --- a/lib/jam_ruby/constants/notification_types.rb +++ b/lib/jam_ruby/constants/notification_types.rb @@ -1,7 +1,8 @@ module NotificationTypes - FRIEND_UPDATE = "friend_update" - FRIEND_REQUEST = "friend_request" - FRIEND_REQUEST_ACCEPTED = "friend_request_accepted" + FRIEND_UPDATE = "FRIEND_UPDATE" + FRIEND_REQUEST = "FRIEND_REQUEST" + FRIEND_REQUEST_ACCEPTED = "FRIEND_REQUEST_ACCEPTED" + SESSION_INVITATION = "SESSION_INVITATION" end \ No newline at end of file diff --git a/lib/jam_ruby/message_factory.rb b/lib/jam_ruby/message_factory.rb index efcffd1aa..6396895de 100644 --- a/lib/jam_ruby/message_factory.rb +++ b/lib/jam_ruby/message_factory.rb @@ -118,8 +118,8 @@ end # create a friend request message - def friend_request(id, user_id, name, photo_url, friend_id, msg, notification_id, created_at) - friend_request = Jampb::FriendRequest.new(:id => id, + def friend_request(friend_request_id, user_id, name, photo_url, friend_id, msg, notification_id, created_at) + friend_request = Jampb::FriendRequest.new(:friend_request_id => friend_request_id, :user_id => user_id, :name => name, :photo_url => photo_url, :friend_id => friend_id, :msg => msg, :notification_id => notification_id, :created_at => created_at) diff --git a/lib/jam_ruby/models/notification.rb b/lib/jam_ruby/models/notification.rb index 561ccf058..7e7dc44a8 100644 --- a/lib/jam_ruby/models/notification.rb +++ b/lib/jam_ruby/models/notification.rb @@ -138,7 +138,7 @@ module JamRuby end ################### FRIEND REQUEST ################### - def send_friend_request(id, user_id, friend_id) + def send_friend_request(friend_request_id, user_id, friend_id) user = User.find(user_id) # (1) save to database @@ -146,11 +146,12 @@ module JamRuby notification.description = NotificationTypes::FRIEND_REQUEST notification.source_user_id = user_id notification.target_user_id = friend_id + notification.friend_request_id = friend_request_id notification.save # (2) create notification notification_msg = format_msg(NotificationTypes::FRIEND_REQUEST, user) - msg = @@message_factory.friend_request(id, user_id, user.name, user.photo_url, friend_id, notification_msg, notification.id, notification.created_at.to_s) + 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 @@mq_router.publish_to_user(friend_id, msg) @@ -180,7 +181,7 @@ module JamRuby # (1) save to database notification = Notification.new - notification.description = "session_invitation" + notification.description = NotificationTypes::SESSION_INVITATION notification.target_user_id = receiver_id notification.save