jam-cloud/ruby/lib/jam_ruby/models/music_session.rb

245 lines
8.9 KiB
Ruby

module JamRuby
class MusicSession < ActiveRecord::Base
NO_RECURRING = 'once'
RECURRING_WEEKLY = 'weekly'
RECURRING_MODES = [NO_RECURRING, RECURRING_WEEKLY]
attr_accessor :legal_terms, :recurring_mode
self.table_name = "music_sessions"
self.primary_key = 'id'
belongs_to :creator,:class_name => 'JamRuby::User', :foreign_key => :user_id, :inverse_of => :music_session_histories
belongs_to :band, :class_name => 'JamRuby::Band', :foreign_key => :band_id, :inverse_of => :music_sessions
belongs_to :active_music_session, :class_name => 'JamRuby::ActiveMusicSession', foreign_key: :music_session_id
has_many :music_session_user_histories, :class_name => "JamRuby::MusicSessionUserHistory", :foreign_key => "music_session_id", :dependent => :delete_all
has_many :comments, :class_name => "JamRuby::MusicSessionComment", :foreign_key => "music_session_id"
has_many :likes, :class_name => "JamRuby::MusicSessionLiker", :foreign_key => "session_id"
has_many :plays, :class_name => "JamRuby::PlayablePlay", :as => :playable, :dependent => :destroy
has_one :share_token, :class_name => "JamRuby::ShareToken", :inverse_of => :shareable, :foreign_key => 'shareable_id'
has_one :feed, :class_name => "JamRuby::Feed", :inverse_of => :music_session, :foreign_key => 'music_session_id', :dependent => :destroy
belongs_to :genre, :class_name => "JamRuby::Genre", :inverse_of => :music_sessions, :foreign_key => 'genre_id'
has_many :join_requests, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::JoinRequest", :foreign_key => "music_session_id"
has_many :invitations, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::Invitation", :foreign_key => "music_session_id"
has_many :invited_musicians, :through => :invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id", :source => :receiver
has_many :fan_invitations, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::FanInvitation", :foreign_key => "music_session_id"
has_many :invited_fans, :through => :fan_invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id", :source => :receiver
validates :genre, :presence => true
validates :description, :presence => true, :no_profanity => true
validates :fan_chat, :inclusion => {:in => [true, false]}
validates :fan_access, :inclusion => {:in => [true, false]}
validates :approval_required, :inclusion => {:in => [true, false]}
validates :musician_access, :inclusion => {:in => [true, false]}
validates :legal_terms, :inclusion => {:in => [true]}, :on => :create
validates :creator, :presence => true
# validates :recurring_mode, :inclusion => {:in => RECURRING_MODES}, :on => :create
validate :creator_is_musician
before_create :generate_share_token
before_create :add_to_feed
SHARE_TOKEN_LENGTH = 8
SEPARATOR = '|'
def add_to_feed
feed = Feed.new
feed.music_session = self
end
def comment_count
self.comments.size
end
def grouped_tracks
tracks = []
self.music_session_user_histories.each do |msuh|
user = User.find(msuh.user_id)
t = Track.new
t.musician = user
t.instrument_ids = []
# this treats each track as a "user", which has 1 or more instruments in the session
unless msuh.instruments.blank?
instruments = msuh.instruments.split(SEPARATOR)
instruments.each do |instrument|
if !t.instrument_ids.include? instrument
t.instrument_ids << instrument
end
end
end
tracks << t
end
tracks
end
def self.index(current_user, user_id, band_id = nil, genre = nil)
hide_private = false
if current_user.id != user_id
hide_private = false # TODO: change to true once public flag exists
end
query = MusicSession
.joins(
%Q{
LEFT OUTER JOIN
music_sessions_user_history
ON
music_sessions.id = music_sessions_user_history.music_session_id
}
)
.where(
%Q{
music_sessions.user_id = '#{user_id}'
}
)
#query = query.where("public = false") unless !hide_private
query = query.where("music_sessions.band_id = '#{band_id}") unless band_id.nil?
query = query.where("music_sessions.genres like '%#{genre}%'") unless genre.nil?
return query
end
def self.create user, params
band = Band.find(params[:band]) unless params[:band].nil?
ms = MusicSession.new
ms.name = params[:description][0..40]
ms.description = params[:description]
ms.musician_access = params[:musician_access]
ms.approval_required = params[:approval_required]
ms.fan_access = params[:fan_access]
ms.fan_chat = params[:fan_chat]
ms.band = band
ms.legal_policy = params[:legal_policy]
ms.language = params[:language]
ms.genre_id = (params[:genres].length > 0 ? params[:genres][0] : nil) if params[:genres]
ms.legal_terms = true
ms.creator = user
ms.save
end
def unique_users
User
.joins(:music_session_user_histories)
.group("users.id")
.order("users.id")
.where(%Q{ music_sessions_user_history.music_session_id = '#{id}'})
end
# returns one user history per user, with instruments all crammed together, and with total duration
def unique_user_histories
MusicSessionUserHistory
.joins(:user)
.select("STRING_AGG(instruments, '|') AS total_instruments,
SUM(date_part('epoch', COALESCE(music_sessions_user_history.session_removed_at, music_sessions_user_history.created_at) - music_sessions_user_history.created_at)) AS total_duration,
music_sessions_user_history.user_id, music_sessions_user_history.music_session_id, users.first_name, users.last_name, users.photo_url")
.group("music_sessions_user_history.user_id, music_sessions_user_history.music_session_id, users.first_name, users.last_name, users.photo_url")
.order("music_sessions_user_history.user_id")
.where(%Q{ music_sessions_user_history.music_session_id = '#{id}'})
end
def duration_minutes
end_time = self.session_removed_at || Time.now
(end_time - self.created_at) / 60.0
end
def music_session_user_histories
@msuh ||= JamRuby::MusicSessionUserHistory
.where(:music_session_id => self.id)
.order('created_at DESC')
end
def comments
@comments ||= JamRuby::MusicSessionComment
.where(:music_session_id => self.id)
.order('created_at DESC')
end
def likes
@likes ||= JamRuby::MusicSessionLiker
.where(:music_session_id => self.music_session_id)
end
# these are 'users that are a part of this session'
# which means are currently in the music_session, or, rsvp'ed, or creator
def part_of_session? user
# XXX check RSVP'ed
user == self.creator || (active_music_session ? active_music_session.users.exists?(user) : false)
end
def is_over?
active_music_session.nil?
end
def has_mount?
active_music_session && active_music_session.mount
end
def recordings
Recording.where(music_session_id: self.id)
end
def end_history
self.update_attribute(:session_removed_at, Time.now)
# ensure all user histories are closed
music_session_user_histories.each do |music_session_user_history|
music_session_user_history.end_history
# then update any users that need their user progress updated
if music_session_user_history.duration_minutes > 15 && music_session_user_history.max_concurrent_connections >= 3
music_session_user_history.user.update_progression_field(:first_real_music_session_at)
end
end
end
def self.removed_music_session(session_id)
hist = self
.where(:id => session_id)
.limit(1)
.first
hist.end_history if hist
Notification.send_session_ended(session_id)
end
def remove_non_alpha_num(token)
token.gsub(/[^0-9A-Za-z]/, '')
end
private
def generate_share_token
token = loop do
token = SecureRandom.urlsafe_base64(SHARE_TOKEN_LENGTH, false)
token = remove_non_alpha_num(token)
token.upcase!
break token unless ShareToken.exists?(token: token)
end
self.share_token = ShareToken.new
self.share_token.token = token
self.share_token.shareable_type = "session"
end
def creator_is_musician
unless creator && creator.musician?
errors.add(:creator, ValidationMessages::MUST_BE_A_MUSICIAN)
end
end
end
end