2012-11-16 02:08:37 +00:00
|
|
|
module JamRuby
|
|
|
|
|
class Recording < ActiveRecord::Base
|
|
|
|
|
|
|
|
|
|
self.primary_key = 'id'
|
|
|
|
|
|
2013-01-22 22:03:23 +00:00
|
|
|
has_and_belongs_to_many :users, :class_name => "JamRuby::User"
|
|
|
|
|
belongs_to :owner, :class_name => "JamRuby::User", :inverse_of => :owned_recording
|
2013-01-22 19:15:52 +00:00
|
|
|
belongs_to :band, :class_name => "JamRuby::Band", :inverse_of => :recording
|
2013-01-24 01:48:13 +00:00
|
|
|
belongs_to :music_session, :class_name => "JamRuby::MusicSession", :inverse_of => :recording
|
2013-01-22 19:15:52 +00:00
|
|
|
|
|
|
|
|
has_many :recorded_tracks, :class_name => "JamRuby::RecordedTrack", :foreign_key => :recording_id
|
2012-11-16 02:08:37 +00:00
|
|
|
|
2012-12-02 07:06:51 +00:00
|
|
|
# genres
|
|
|
|
|
has_and_belongs_to_many :genres, :class_name => "JamRuby::Genre", :join_table => "recordings_genres"
|
|
|
|
|
|
2012-11-21 19:48:39 +00:00
|
|
|
# favorites
|
2012-12-04 03:39:57 +00:00
|
|
|
has_many :favorites, :class_name => "JamRuby::UserFavorite", :foreign_key => "recording_id"
|
|
|
|
|
has_many :inverse_favorites, :through => :favorites, :source => :recording, :class_name => "JamRuby::Recording"
|
2012-11-16 02:08:37 +00:00
|
|
|
|
2012-11-25 19:37:54 +00:00
|
|
|
validates :description, presence: true, length: { maximum: 200 }
|
2012-11-21 19:48:39 +00:00
|
|
|
|
2012-12-04 03:39:57 +00:00
|
|
|
def favorite_count
|
|
|
|
|
return self.favorites.size
|
|
|
|
|
end
|
|
|
|
|
|
2013-01-22 19:15:52 +00:00
|
|
|
# Start recording a session.
|
|
|
|
|
def self.start(music_session_id, creator_id)
|
2013-01-24 01:48:13 +00:00
|
|
|
# Use a transaction and lock to avoid races.
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
music_session = MusicSession.find(music_session_id, :lock => true)
|
2013-01-22 19:15:52 +00:00
|
|
|
|
2013-01-24 01:48:13 +00:00
|
|
|
if music_session.nil?
|
|
|
|
|
raise PermissionError, "the session has ended"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if music_session.recording
|
2013-01-22 19:15:52 +00:00
|
|
|
raise PermissionError, "the session is already being recorded"
|
2013-01-24 01:48:13 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
music_session.recording = true
|
2013-01-22 19:15:52 +00:00
|
|
|
|
2013-01-24 01:48:13 +00:00
|
|
|
recording = Recording.new
|
|
|
|
|
recording.music_session = music_session
|
|
|
|
|
|
|
|
|
|
music_session.connections.each do |connection|
|
|
|
|
|
recording.users << connection.user
|
|
|
|
|
connection.tracks.each do |track|
|
|
|
|
|
RecordedTrack.create_from_track(track, recording)
|
|
|
|
|
end
|
2013-01-22 19:15:52 +00:00
|
|
|
end
|
2013-01-22 22:03:23 +00:00
|
|
|
|
2013-01-24 01:48:13 +00:00
|
|
|
music_session.genres.each do |genre|
|
|
|
|
|
recording.genres << genre
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# Note that I believe this can be nil.
|
|
|
|
|
recording.band_id = music_session.band_id
|
|
|
|
|
recording.save
|
|
|
|
|
|
|
|
|
|
music_session.save
|
2013-01-22 22:03:23 +00:00
|
|
|
end
|
2013-01-22 19:15:52 +00:00
|
|
|
end
|
|
|
|
|
|
2013-01-24 01:48:13 +00:00
|
|
|
# Stop recording a session
|
|
|
|
|
def stop
|
|
|
|
|
# Use a transaction and lock to avoid races.
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
music_session = MusicSession.find(self.music_session_id, :lock => true)
|
|
|
|
|
if music_session.nil?
|
|
|
|
|
raise PermissionError, "the session has ended"
|
|
|
|
|
end
|
|
|
|
|
unless music_session.recording
|
|
|
|
|
raise PermissionError, "the session is not currently being recorded"
|
|
|
|
|
end
|
|
|
|
|
music_session.recording = false
|
|
|
|
|
music_session.save
|
|
|
|
|
end
|
|
|
|
|
end
|
2013-01-22 19:15:52 +00:00
|
|
|
|
2013-01-14 04:50:38 +00:00
|
|
|
def self.search(query, options = { :limit => 10 })
|
|
|
|
|
|
|
|
|
|
# only issue search if at least 2 characters are specified
|
|
|
|
|
if query.nil? || query.length < 2
|
|
|
|
|
return []
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# create 'anded' statement
|
|
|
|
|
query = Search.create_tsquery(query)
|
|
|
|
|
|
|
|
|
|
if query.nil? || query.length == 0
|
|
|
|
|
return []
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return Recording.where("description_tsv @@ to_tsquery('jamenglish', ?)", query).limit(options[:limit])
|
|
|
|
|
end
|
|
|
|
|
|
2013-01-22 19:15:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-12-02 07:06:51 +00:00
|
|
|
def self.save(id, is_public, description, genres, updater_id, owner_id, is_band)
|
2012-11-22 08:27:23 +00:00
|
|
|
|
2013-01-22 19:15:52 +00:00
|
|
|
# Spec: https://jamkazam.atlassian.net/wiki/display/PS/Product+Specification+-+Studio
|
|
|
|
|
# This is seriously wrong. A recording needs to be created from inside a session. I'm not sure who owns
|
|
|
|
|
# the recording, but I do know that it's affiliated with the session and then should be able to get the band id
|
|
|
|
|
# and probably all this other stuff (genre, etc) from that. I need to read the recording spec in more detail
|
|
|
|
|
# to figure that out. I'll read it on bart.
|
|
|
|
|
#
|
|
|
|
|
# The studio spec is the key here. A couple notes:
|
|
|
|
|
# * Multiple musicians are all associated with a recording -- everyone who is in the music session when the recording starts
|
|
|
|
|
# * Associating a band with the recording is optional
|
|
|
|
|
# * The recording needs to be associated with a music_session for sure. Probably also a set of tracks (NOT musicians). Then, on
|
|
|
|
|
# recording completion is when you have the track -> saved_track (rename this to recorded_track) transition.
|
|
|
|
|
# * The metadata in general is filled in *after* the recording ends. This is important because it means the save method below
|
|
|
|
|
# is sort of jacked.
|
2012-11-22 08:27:23 +00:00
|
|
|
creator = User.find(updater_id)
|
|
|
|
|
|
|
|
|
|
if is_band
|
|
|
|
|
band = Band.find(owner_id)
|
|
|
|
|
validate_user_is_band_member(creator, band)
|
|
|
|
|
else
|
|
|
|
|
user = User.find(owner_id)
|
|
|
|
|
validate_user_is_creator(user, creator)
|
|
|
|
|
validate_user_is_musician(user)
|
|
|
|
|
end
|
|
|
|
|
|
2012-11-21 19:48:39 +00:00
|
|
|
if id.nil?
|
2012-12-02 07:06:51 +00:00
|
|
|
validate_genres(genres, false)
|
2012-11-21 19:48:39 +00:00
|
|
|
recording = Recording.new()
|
2012-11-22 08:27:23 +00:00
|
|
|
recording.creator_id = updater_id
|
2012-11-21 19:48:39 +00:00
|
|
|
else
|
2012-12-02 07:06:51 +00:00
|
|
|
validate_genres(genres, true)
|
2012-11-21 19:48:39 +00:00
|
|
|
recording = Recording.find(id)
|
|
|
|
|
end
|
|
|
|
|
|
2012-11-22 08:27:23 +00:00
|
|
|
recording.updater_id = updater_id
|
|
|
|
|
|
2012-11-21 19:48:39 +00:00
|
|
|
# public flag
|
|
|
|
|
unless is_public.nil?
|
|
|
|
|
recording.public = is_public
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# description
|
|
|
|
|
unless description.nil?
|
|
|
|
|
recording.description = description
|
|
|
|
|
end
|
|
|
|
|
|
2012-12-02 07:06:51 +00:00
|
|
|
# genres
|
|
|
|
|
unless genres.nil?
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
# delete all genres for this recording first
|
|
|
|
|
unless recording.id.nil? || recording.id.length == 0
|
|
|
|
|
recording.genres.delete_all
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# loop through each genre in the array and save to the db
|
|
|
|
|
genres.each do |genre_id|
|
|
|
|
|
g = Genre.find(genre_id)
|
|
|
|
|
recording.genres << g
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2012-11-22 08:27:23 +00:00
|
|
|
recording.updated_at = Time.now.getutc
|
|
|
|
|
|
|
|
|
|
# TODO: wrap in transaction with statements below
|
|
|
|
|
recording.save
|
|
|
|
|
|
2012-11-24 18:22:44 +00:00
|
|
|
if id.nil?
|
|
|
|
|
if is_band
|
|
|
|
|
recording.band_recordings << BandRecording.create(band_id: owner_id, recording_id: recording.id)
|
|
|
|
|
else
|
|
|
|
|
recording.musician_recordings << MusicianRecording.create(user_id: owner_id, recording_id: recording.id)
|
|
|
|
|
end
|
2012-11-21 19:48:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return recording
|
|
|
|
|
end
|
|
|
|
|
|
2012-11-22 08:27:23 +00:00
|
|
|
private
|
|
|
|
|
def self.validate_user_is_band_member(user, band)
|
|
|
|
|
unless band.users.exists? user
|
2012-11-24 18:22:44 +00:00
|
|
|
raise PermissionError, ValidationMessages::USER_NOT_BAND_MEMBER_VALIDATION_ERROR
|
2012-11-22 08:27:23 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.validate_user_is_creator(user, creator)
|
|
|
|
|
unless user.id == creator.id
|
2012-11-24 18:22:44 +00:00
|
|
|
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
2012-11-22 08:27:23 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.validate_user_is_musician(user)
|
|
|
|
|
unless user.musician?
|
2012-11-24 18:22:44 +00:00
|
|
|
raise PermissionError, ValidationMessages::USER_NOT_MUSICIAN_VALIDATION_ERROR
|
2012-11-22 08:27:23 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2012-12-02 07:06:51 +00:00
|
|
|
def self.validate_genres(genres, is_nil_ok)
|
|
|
|
|
if is_nil_ok && genres.nil?
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if genres.nil?
|
|
|
|
|
raise JamRuby::JamArgumentError, ValidationMessages::GENRE_MINIMUM_NOT_MET
|
|
|
|
|
else
|
|
|
|
|
if genres.size < Limits::MIN_GENRES_PER_RECORDING
|
|
|
|
|
raise JamRuby::JamArgumentError, ValidationMessages::GENRE_MINIMUM_NOT_MET
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if genres.size > Limits::MAX_GENRES_PER_RECORDING
|
|
|
|
|
raise JamRuby::JamArgumentError, ValidationMessages::GENRE_LIMIT_EXCEEDED
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2012-11-22 08:27:23 +00:00
|
|
|
=begin
|
2012-11-21 19:48:39 +00:00
|
|
|
def self.delete(id, owner_id, is_band)
|
|
|
|
|
if is_band?
|
2012-11-22 08:27:23 +00:00
|
|
|
JamRuby::Recording.delete_all "(user_id = '#{user_id}' AND follower_id = '#{follower_id}')"
|
2012-11-21 19:48:39 +00:00
|
|
|
else
|
|
|
|
|
end
|
|
|
|
|
end
|
2012-11-22 08:27:23 +00:00
|
|
|
=end
|
2012-11-16 02:08:37 +00:00
|
|
|
end
|
2013-01-22 22:03:23 +00:00
|
|
|
end
|