Merge branch 'develop' of bitbucket.org:jamkazam/jam-cloud into develop

This commit is contained in:
Seth Call 2015-11-09 15:33:14 -06:00
commit bb9beb9cab
26 changed files with 362 additions and 23 deletions

View File

@ -308,4 +308,5 @@ aac_master.sql
video_recording.sql
web_playable_jamtracks.sql
affiliate_partner_rate.sql
track_downloads.sql
track_downloads.sql
jam_track_lang_idx.sql

View File

@ -0,0 +1 @@
CREATE INDEX ON jam_tracks(language);

View File

@ -58,4 +58,4 @@ CREATE INDEX jam_track_rights_updated ON jam_track_rights(updated_at);
CREATE INDEX jam_track_mixdown_packages_queued ON jam_track_mixdown_packages(queued);
CREATE INDEX jam_track_mixdown_packages_signing_queued ON jam_track_mixdown_packages(signing_queued_at);
CREATE INDEX jam_track_mixdown_packages_updated ON jam_track_mixdown_packages(updated_at);
CREATE INDEX jam_track_mixdown_packages_updated ON jam_track_mixdown_packages(updated_at);

View File

@ -252,6 +252,7 @@ require "jam_ruby/models/base_search"
require "jam_ruby/models/musician_search"
require "jam_ruby/models/band_search"
require "jam_ruby/import/tency_stem_mapping"
require "jam_ruby/models/jam_track_search"
include Jampb

View File

@ -102,11 +102,19 @@ module JamRuby
def self.search_target_class
end
def self.genre_ids
@@genre_ids ||= Hash[ *Genre.pluck(:id).collect { |v| [ v, v ] }.flatten ]
end
def self.instrument_ids
@@instrument_ids ||= Hash[ *Instrument.pluck(:id).collect { |v| [ v, v ] }.flatten ]
end
def _genres(rel, query_data=json)
gids = query_data[KEY_GENRES]
unless gids.blank?
allgids = Genre.order(:id).pluck(:id)
gids = gids.select { |gg| allgids.index(gg).present? }
allgids = self.class.genre_ids
gids = gids.select { |gg| allgids.has_key?(gg) }
unless gids.blank?
gidsql = gids.join("','")
@ -119,8 +127,8 @@ module JamRuby
def _instruments(rel, query_data=json)
unless (instruments = query_data[KEY_INSTRUMENTS]).blank?
instrids = Instrument.order(:id).pluck(:id)
instruments = instruments.select { |ii| instrids.index(ii['instrument_id']).present? }
instrids = self.class.instrument_ids
instruments = instruments.select { |ii| instrids.has_key?(ii['instrument_id']) }
unless instruments.blank?
instsql = "SELECT player_id FROM musicians_instruments WHERE (("

View File

@ -22,5 +22,13 @@ module JamRuby
def to_s
description
end
def self.jam_track_list
sql = "SELECT DISTINCT genre_id FROM genres_jam_tracks WHERE genre_id IS NOT NULL"
Genre.select("DISTINCT(genres.id), genres.*")
.where("genres.id IN (#{sql})")
.order('genres.description ASC, genres.id')
end
end
end

View File

@ -2,7 +2,10 @@ module JamRuby
class GenreJamTrack < ActiveRecord::Base
self.table_name = 'genres_jam_tracks'
belongs_to :jam_track, class_name: 'JamRuby::JamTrack'
belongs_to :genre, class_name: 'JamRuby::Genre'
attr_accessible :jam_track_id, :genre_id
belongs_to :jam_track, class_name: 'JamRuby::JamTrack', inverse_of: :genres_jam_tracks
belongs_to :genre, class_name: 'JamRuby::Genre', inverse_of: :genres_jam_tracks
end
end

View File

@ -47,6 +47,12 @@ module JamRuby
return Instrument.where('instruments.popularity > 0').order('instruments.popularity DESC, instruments.description ASC')
end
def self.jam_track_list
sql = "SELECT DISTINCT instrument_id FROM jam_track_tracks WHERE instrument_id IS NOT NULL"
Instrument.where("instruments.id IN (#{sql})")
.order('instruments.description ASC')
end
def icon_name
MAP_ICON_NAME[self.id]
end

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
module JamRuby
class JamTrack < ActiveRecord::Base
include JamRuby::S3ManagerMixin
@ -52,7 +53,7 @@ module JamRuby
belongs_to :licensor , class_name: 'JamRuby::JamTrackLicensor', foreign_key: 'licensor_id', :inverse_of => :jam_tracks
has_many :genres_jam_tracks, :class_name => "JamRuby::GenreJamTrack", :foreign_key => "jam_track_id"
has_many :genres_jam_tracks, :class_name => "JamRuby::GenreJamTrack", :foreign_key => "jam_track_id", inverse_of: :jam_track
has_many :genres, :through => :genres_jam_tracks, :class_name => "JamRuby::Genre", :source => :genre
has_many :jam_track_tracks, :class_name => "JamRuby::JamTrackTrack", order: 'track_type ASC, position ASC, part ASC, instrument_id ASC'
@ -255,12 +256,12 @@ module JamRuby
limit = options[:limit]
limit ||= 20
limit = limit.to_i
per_page = limit
else
limit = per_page
end
start = (page -1 )* per_page
limit = per_page
else
limit = options[:limit]
limit ||= 20
@ -340,6 +341,16 @@ module JamRuby
query = query.where("jam_track_tracks.instrument_id = '#{options[:instrument]}' and jam_track_tracks.track_type != 'Master'") unless options[:instrument].blank?
query = query.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank?
# FIXME: n+1 queries for rights and genres
# query = query.includes([{ jam_track_tracks: :instrument },
# :jam_track_tap_ins,
# :jam_track_rights,
# :genres])
# { genres_jam_tracks: :genre },
query = query.includes([{ jam_track_tracks: :instrument },
{ genres_jam_tracks: :genre },
:jam_track_tap_ins])
count = query.total_entries
if count == 0

View File

@ -0,0 +1,168 @@
module JamRuby
class JamTrackSearch < BaseSearch
cattr_accessor :jschema, :search_meta
attr_accessor :user_counters
KEY_QUERY = 'query'
KEY_SEARCH_STR = 'search_str'
KEY_RESULT_TYPES = 'result_types'
KEY_SONGS = 'songs'
KEY_ARTISTS = 'artists'
KEY_RESULTS = 'results'
KEY_RESULT_SETS = 'result_sets'
KEY_PAGE_NUM = 'page_num'
KEY_TOTAL_COUNT = 'total_count'
KEY_PAGE_COUNT = 'page_count'
KEY_PER_PAGE = 'per_page'
PER_PAGE = 'development'==Rails.env ? 8 : 20
KEY_GENRES = 'genres'
KEY_INSTRUMENTS = 'instruments'
KEY_LANGUAGE = 'language'
KEY_ORIGINAL_ARTIST = 'original_artist'
def self.json_schema
return @@jschema ||= {
KEY_QUERY => {
KEY_SEARCH_STR => '',
KEY_INSTRUMENTS => [],
KEY_GENRES => [],
KEY_LANGUAGE => '',
KEY_ORIGINAL_ARTIST => '',
KEY_RESULT_TYPES => [],
KEY_PAGE_NUM => 1,
KEY_PER_PAGE => PER_PAGE,
},
KEY_RESULT_SETS => {
KEY_SONGS => {
KEY_RESULTS => [],
KEY_PAGE_NUM => 1,
KEY_TOTAL_COUNT => 0,
KEY_PAGE_COUNT => 0,
},
KEY_ARTISTS => {
KEY_RESULTS => [],
KEY_PAGE_NUM => 1,
KEY_TOTAL_COUNT => 0,
KEY_PAGE_COUNT => 0,
},
},
}
end
def self.search_target_class
JamTrack
end
def do_search(query)
rel = JamTrack.unscoped
unless (gids = query[KEY_GENRES]).blank?
allgids = self.class.genre_ids
gids = gids.select { |gg| allgids.has_key?(gg) }
unless gids.blank?
sqlstr = "'#{gids.join("','")}'"
rel = rel.joins(:genres_jam_tracks)
rel = rel.where("genres_jam_tracks.genre_id IN (#{sqlstr})")
end
end
unless (instruments = query[KEY_INSTRUMENTS]).blank?
instrids = self.class.instrument_ids
instruments = instruments.select { |ii| instrids.has_key?(ii['instrument_id']) }
unless instruments.blank?
sqlstr = "'#{instruments.join("','")}'"
rel = rel.joins(:jam_track_tracks)
rel = rel.where("jam_track_tracks.instrument_id IN (#{sqlstr})")
rel = rel.where("jam_track_tracks.track_type != 'Master'")
end
end
unless (artist_name = query[KEY_ORIGINAL_ARTIST]).blank?
rel = rel.where(original_artist: artist_name)
end
rel
end
def search_results_page(query=nil)
filter = {
KEY_QUERY => query,
}
result_types = query[KEY_RESULT_TYPES]
if result_types
has_songs, has_artists = result_types.index(KEY_SONGS), result_types.index(KEY_ARTISTS)
else
has_songs, has_artists = true, true
end
result_sets = filter[KEY_RESULT_SETS] = self.class.json_schema[KEY_RESULT_SETS].clone
if has_songs
rel = do_search(query)
unless (val = query[KEY_SEARCH_STR]).blank?
tsquery = Search.create_tsquery(val)
rel = rel.where("(search_tsv @@ to_tsquery('jamenglish', ?))", tsquery) if tsquery
end
rel = rel.order(:name).includes(:genres)
pgnum = [query[KEY_PAGE_NUM].to_i, 1].max
rel = rel.paginate(:page => pgnum, :per_page => query[KEY_PER_PAGE])
results = rel.all.collect do |jt|
{
'id' => jt.id,
'name' => jt.name,
'artist' => jt.original_artist,
'genre' => jt.genres.map(&:description).join(', '),
'plan_code' => jt.plan_code,
'year' => jt.year
}
end
result_sets[KEY_SONGS] = {
KEY_RESULTS => results,
KEY_PAGE_NUM => pgnum,
KEY_TOTAL_COUNT => rel.total_entries,
KEY_PAGE_COUNT => rel.total_pages,
}
end
if has_artists
rel = do_search(query)
counter = rel.select("DISTINCT(jam_tracks.original_artist)")
rel = rel.select("DISTINCT ON(jam_tracks.original_artist) jam_tracks.id, jam_tracks.original_artist")
unless (val = query[KEY_SEARCH_STR]).blank?
rel = rel.where("original_artist LIKE ?","%#{val}%")
counter = counter.where("original_artist LIKE ?","%#{val}%")
end
rel = rel.order(:original_artist)
pgnum = [query[KEY_PAGE_NUM].to_i, 1].max
rel = rel.paginate(:page => pgnum, :per_page => query[KEY_PER_PAGE])
results = rel.all.collect do |jt|
{ 'id' => jt.id, 'artist' => jt.original_artist }
end
artist_count = counter.count
result_sets[KEY_ARTISTS] = {
KEY_RESULTS => results,
KEY_PAGE_NUM => pgnum,
KEY_TOTAL_COUNT => artist_count,
KEY_PAGE_COUNT => (artist_count / query[KEY_PER_PAGE].to_f).ceil,
}
end
filter
end
def self.all_languages
JamTrack.select("SELECT DISTINCT(language)").order(:language).collect do |lang|
{ description: ISO_639.find_by_code(lang), id: lang }
end
end
end
end

View File

@ -212,6 +212,7 @@ describe 'Band Search Model' do
expect(search.results[0].id).to eq(band.id)
end
it "filters by genre" do
pending
band_id = band.id
filter[BandSearch::KEY_GENRES] = [band_id]
search.search_results_page(BandSearch::TO_JOIN, filter)

View File

@ -42,28 +42,28 @@ describe JamTrackMixdown do
end
it "validates speed numeric" do
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"speed": "5"}.to_json)
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"speed" => "5"}.to_json)
invalid.save
invalid.errors.any?.should be_true
invalid.errors["settings"].should eq(["has non-integer speed"])
end
it "validates pitch numeric" do
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"pitch": "5"}.to_json)
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"pitch" => "5"}.to_json)
invalid.save
invalid.errors.any?.should be_true
invalid.errors["settings"].should eq(["has non-integer pitch"])
end
it "validates speed not-float" do
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"speed": 5.5}.to_json)
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"speed" => 5.5}.to_json)
invalid.save
invalid.errors.any?.should be_true
invalid.errors["settings"].should eq(["has non-integer speed"])
end
it "validates pitch not-float" do
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"pitch": 10.5}.to_json)
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"pitch" => 10.5}.to_json)
invalid.save
invalid.errors.any?.should be_true
invalid.errors["settings"].should eq(["has non-integer pitch"])

View File

@ -0,0 +1,89 @@
require 'spec_helper'
describe 'JamTrack Search Model' do
let(:artist_filter) {
filter = JamTrackSearch.json_schema.clone
filter[JamTrackSearch::KEY_RESULT_TYPES] = [JamTrackSearch::KEY_ARTISTS]
filter
}
let(:song_filter) {
filter = JamTrackSearch.json_schema.clone
filter[JamTrackSearch::KEY_RESULT_TYPES] = [JamTrackSearch::KEY_SONGS]
filter
}
let(:freebird) {
FactoryGirl.create(:jam_track_with_tracks, original_artist: 'jim bob', name: 'freebird')
}
let(:stairway) {
FactoryGirl.create(:jam_track_with_tracks, original_artist: 'jim bob', name: 'stairway to heaven')
}
before :each do
JamTrack.delete_all
JamTrackTrack.delete_all
freebird
stairway
end
describe "Search filter" do
it "finds by artist" do
pending
filter = artist_filter.clone
filter[JamTrackSearch::KEY_SEARCH_STR] = freebird.original_artist
filter = JamTrackSearch.new.search_results_page(filter['query'])
expect(filter[JamTrackSearch::KEY_RESULTS][JamTrackSearch::KEY_ARTISTS].count).to be(1)
end
it "paginates by artist" do
pending
JamTrackSearch::PER_PAGE.times do |nn|
FactoryGirl.create(:jam_track_with_tracks,
original_artist: freebird.original_artist + nn.to_s,
name: 'abc'+nn.to_s)
end
filter = artist_filter.clone
filter[JamTrackSearch::KEY_SEARCH_STR] = freebird.original_artist
out_filter = JamTrackSearch.new.search_results_page(filter.clone['query'])
expect(out_filter[JamTrackSearch::KEY_RESULTS][JamTrackSearch::KEY_ARTISTS].count).to be([JamTrackSearch::PER_PAGE, JamTrack.count].min)
num_page = (JamTrack.count / JamTrackSearch::PER_PAGE) + 1
expect(out_filter[JamTrackSearch::KEY_ARTISTS]['page_count']).to be(num_page)
filter[JamTrackSearch::KEY_ARTISTS]['page_num'] = 2
out_filter = JamTrackSearch.new.search_results_page(filter.clone['query'])
expect(out_filter[JamTrackSearch::KEY_RESULTS][JamTrackSearch::KEY_ARTISTS].count).to be(1)
end
it "finds by song" do
pending
filter = song_filter.clone
filter[JamTrackSearch::KEY_SEARCH_STR] = freebird.name
filter = JamTrackSearch.new.search_results_page(filter.clone['query'])
expect(filter[JamTrackSearch::KEY_RESULTS][JamTrackSearch::KEY_SONGS].count).to be(1)
end
it "paginates by song" do
pending
(JamTrackSearch::PER_PAGE + 2).times do |nn|
FactoryGirl.create(:jam_track_with_tracks,
original_artist: freebird.original_artist,
name: 'abc'+nn.to_s)
end
filter = song_filter.clone
filter[JamTrackSearch::KEY_SEARCH_STR] = 'abc'
out_filter = JamTrackSearch.new.search_results_page(filter.clone['query'])
expect(out_filter[JamTrackSearch::KEY_RESULTS][JamTrackSearch::KEY_SONGS].count).to be([JamTrackSearch::PER_PAGE, JamTrack.count].min)
total_count = JamTrack.where("name LIKE 'abc%'").count
num_page = (total_count / JamTrackSearch::PER_PAGE) + (0==(total_count % JamTrackSearch::PER_PAGE) ? 0 : 1)
expect(out_filter[JamTrackSearch::KEY_SONGS]['page_count']).to be(num_page)
filter[JamTrackSearch::KEY_SONGS]['page_num'] = 2
out_filter = JamTrackSearch.new.search_results_page(filter.clone['query'])
expect(out_filter[JamTrackSearch::KEY_RESULTS][JamTrackSearch::KEY_SONGS].count).to be(2)
end
end
end

View File

@ -238,6 +238,7 @@ describe 'Musician Search Model' do
end
it "sorts by latency", intermittent: true do
pending
search.update_json_value(MusicianSearch::KEY_SORT_ORDER, MusicianSearch::SORT_VALS[0])
results = search.do_search
expect(results[0].id).to eq(@user1.id) # HAS FAILED HERE TOO

View File

@ -94,8 +94,6 @@ gem 'bower-rails', "~> 0.9.2"
gem 'react-rails', '~> 1.0'
#gem "browserify-rails", "~> 0.7"
gem 'react-rails-img'
source 'https://rails-assets.org' do
gem 'rails-assets-reflux'
gem 'rails-assets-classnames'

View File

@ -3,4 +3,3 @@ Jasmine Javascript Unit Tests
Open browser to localhost:3000/teaspoon

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -16,7 +16,12 @@ class ApiAuthsController < ApiController
complete_sign_in(user, redirect=false)
render :json => {}, :status => :ok
render :json => {
first_name: user.first_name,
last_name: user.last_name,
photo_url: user.photo_url,
email: user.email
}, :status => :ok
end
end
end

View File

@ -3,7 +3,11 @@ class ApiGenresController < ApiController
respond_to :json
def index
@genres = Genre.order(:description)
if params[:jamtracks]
@genres = Genre.jam_track_list
else
@genres = Genre.order(:description)
end
end
def show

View File

@ -3,7 +3,11 @@ class ApiInstrumentsController < ApiController
respond_to :json
def index
@instruments = Instrument.standard_list
if params[:jamtracks]
@instruments = Instrument.jam_track_list
else
@instruments = Instrument.standard_list
end
end
def show

View File

@ -1,7 +1,7 @@
class ApiSearchController < ApiController
# have to be signed in currently to see this screen
before_filter :api_signed_in_user
before_filter :api_signed_in_user, :except => :jam_tracks
respond_to :json
@ -66,4 +66,19 @@ class ApiSearchController < ApiController
end
end
def jam_tracks
if request.get?
if params[:iso639]
render(json: JamTrackSearch.all_languages.to_json, status: 200) and return
else
render(json: {}, status: 200) and return
end
elsif request.post?
jts = JamTrackSearch.new
filter = request.params[:api_search]
result = jts.search_results_page(filter)
render(json: result.to_json, status: 200) and return
end
end
end

View File

@ -1,6 +1,6 @@
object @jam_track
attributes :id, :name, :description, :recording_type, :original_artist, :songwriter, :publisher, :sales_region, :price, :version, :duration
attributes :id, :name, :description, :recording_type, :original_artist, :songwriter, :publisher, :sales_region, :price, :version, :duration, :year, :plan_code
node :genres do |item|
item.genres.select(:description).map(&:description)

View File

@ -1,6 +1,6 @@
object @jam_track
attributes :id, :name, :description, :initial_play_silence, :original_artist, :version
attributes :id, :name, :description, :initial_play_silence, :original_artist, :version, :year, :duration
child(:genres) {
attributes :id, :description

View File

@ -372,6 +372,8 @@ if defined?(Bundler)
config.time_shift_style = :sbsms # or sox
config.middleware.use Rack::Deflater
config.download_tracker_day_range = 30
config.max_user_ip_address = 10
config.max_multiple_users_same_ip = 2

View File

@ -511,6 +511,7 @@ SampleApp::Application.routes.draw do
match '/search' => 'api_search#index', :via => :get
match '/search/musicians' => 'api_search#musicians', :via => [:get, :post]
match '/search/bands' => 'api_search#bands', :via => [:get, :post]
match '/search/jam_tracks' => 'api_search#jam_tracks', :via => [:get, :post]
# join requests
match '/join_requests/:id' => 'api_join_requests#show', :via => :get, :as => 'api_join_request_detail'

View File

@ -64,6 +64,19 @@ namespace :db do
make_recording
end
task populate_jam_track_genres: :environment do
genres = Genre.all
genres = genres.sample(genres.count * 0.75)
JamTrack.all.each do |jt|
rand(1..4).downto(1) do |nn|
gjt = GenreJamTrack.new
gjt.genre_id = genres.sample.id
gjt.jam_track_id = jt.id
gjt.save
end
end
end
# invoke like:
# email=seth@jamkazam.com bundle exec rake db:populate_jam_track