module JamRuby class Track < ActiveRecord::Base self.table_name = "tracks" self.primary_key = 'id' default_scope order('created_at ASC') attr_accessor :musician, :instrument_ids SOUND = %w(mono stereo) belongs_to :connection, :class_name => "JamRuby::Connection", :inverse_of => :tracks, :foreign_key => 'connection_id' belongs_to :instrument, :class_name => "JamRuby::Instrument", :inverse_of => :tracks validates :sound, :inclusion => {:in => SOUND} validates :connection, presence: true validates :client_track_id, presence: true #validates :client_resource_id, presence: true def user self.connection.user end def musician @musician end def musician=(user) @musician = user end def self.index(current_user, music_session_id) query = Track .joins( %Q{ INNER JOIN connections ON connections.music_session_id = '#{music_session_id}' AND connections.id = connection_id AND connections.user_id = '#{current_user.id}' INNER JOIN music_sessions ON music_sessions.id = '#{music_session_id}' AND music_sessions.user_id = '#{current_user.id}' } ) return query end def self.diff_track(track_class, existing_tracks, new_tracks, &blk) result = [] if new_tracks.length == 0 existing_tracks.delete_all else # we will prune from this as we find matching tracks to_delete = Set.new(existing_tracks) to_add = Array.new(new_tracks) existing_tracks.each do |existing_track| new_tracks.each do |new_track| if new_track[:id] == existing_track.id || new_track[:client_track_id] == existing_track.client_track_id to_delete.delete(existing_track) to_add.delete(new_track) blk.call(existing_track, new_track) result.push(existing_track) if existing_track.save next else result = existing_track raise ActiveRecord::Rollback end end end end to_add.each do |new_track| existing_track = track_class.new blk.call(existing_track, new_track) if existing_track.save result.push(existing_track) else result = existing_track raise ActiveRecord::Rollback end end to_delete.each do |delete_me| delete_me.delete end end result end # this is a bit different from a normal track synchronization in that the client just sends up all tracks, # ... some may already exist def self.sync(clientId, tracks, backing_tracks = []) result = {} backing_tracks = [] unless backing_tracks Track.transaction do connection = Connection.find_by_client_id!(clientId) # each time tracks are synced we have to update the entry in music_sessions_user_history msh = MusicSessionUserHistory.find_by_client_id!(clientId) instruments = [] tracks.each do |track| instruments << track[:instrument_id] end result[:tracks] = diff_track(Track, connection.tracks, tracks) do |track_record, track_info| track_record.connection = connection track_record.client_track_id = track_info[:client_track_id] track_record.client_resource_id = track_info[:client_resource_id] track_record.instrument_id = track_info[:instrument_id] track_record.sound = track_info[:sound] end result[:backing_tracks] = diff_track(BackingTrack, connection.backing_tracks, backing_tracks) do |track_record, track_info| track_record.connection = connection track_record.client_track_id = track_info[:client_track_id] track_record.client_resource_id = track_info[:client_resource_id] track_record.filename = track_info[:filename] end msh.instruments = instruments.join("|") if !msh.save raise ActiveRecord::Rollback end end result end def self.save(id, connection_id, instrument_id, sound, client_track_id, client_resource_id) if id.nil? track = Track.new track.connection_id = connection_id else track = Track.find(id) end unless instrument_id.nil? track.instrument_id = instrument_id end unless sound.nil? track.sound = sound end unless client_track_id.nil? track.client_track_id = client_track_id end unless client_resource_id.nil? track.client_resource_id = resource_id end track.updated_at = Time.now track.save return track end end end