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

This commit is contained in:
Brian Smith 2014-03-11 19:54:51 -04:00
commit 31d94344b5
20 changed files with 266 additions and 52 deletions

View File

@ -133,4 +133,7 @@ plays_refactor.sql
fix_max_mind_isp_and_geo.sql
update_get_work_for_client_type.sql
events.sql
cascading_delete_constraints_for_release.sql
events_social_description.sql
fix_broken_cities.sql

View File

@ -0,0 +1,18 @@
-- allow a user to be readily deleted by adding cascades
ALTER TABLE music_sessions_user_history DROP CONSTRAINT music_sessions_user_history_user_id_fkey;
ALTER TABLE ONLY music_sessions_user_history ADD CONSTRAINT music_sessions_user_history_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE crash_dumps DROP CONSTRAINT crash_dumps_user_id_fkey;
ALTER TABLE ONLY crash_dumps ADD CONSTRAINT crash_dumps_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE music_sessions_history DROP CONSTRAINT music_sessions_history_user_id_fkey;
ALTER TABLE music_sessions_history ADD CONSTRAINT music_sessions_history_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE music_sessions_user_history DROP CONSTRAINT "music_sessions_user_history_music_session_id_fkey";
ALTER TABLE music_sessions_user_history ADD CONSTRAINT "music_sessions_user_history_music_session_id_fkey" FOREIGN KEY (music_session_id) REFERENCES music_sessions_history(music_session_id) ON DELETE CASCADE;
ALTER TABLE "recordings" DROP CONSTRAINT "recordings_creator_id_fkey";
ALTER TABLE "recordings" ADD CONSTRAINT "recordings_creator_id_fkey" FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE playable_plays DROP CONSTRAINT "playable_plays_claimed_recording_id_fkey";
ALTER TABLE playable_plays ADD CONSTRAINT "playable_plays_claimed_recording_id_fkey" FOREIGN KEY (claimed_recording_id) REFERENCES claimed_recordings(id) ON DELETE CASCADE;

View File

@ -0,0 +1 @@
ALTER TABLE events ADD COLUMN social_description TEXT;

View File

@ -0,0 +1,2 @@
alter table cities drop column regionname;
alter table cities drop column countryname;

View File

@ -128,6 +128,9 @@ require "jam_ruby/models/geo_ip_locations"
require "jam_ruby/models/score"
require "jam_ruby/models/get_work"
require "jam_ruby/models/playable_play"
require "jam_ruby/models/country"
require "jam_ruby/models/region"
require "jam_ruby/models/city"
include Jampb

View File

@ -0,0 +1,10 @@
module JamRuby
class City < ActiveRecord::Base
self.table_name = 'cities'
def self.get_all(country, region)
self.where(countrycode: country).where(region: region).order('city asc').all
end
end
end

View File

@ -0,0 +1,53 @@
module JamRuby
class Country < ActiveRecord::Base
self.table_name = 'countries'
def self.get_all()
self.order('countryname asc').all
end
def self.import_from_iso3166(file)
# File iso3166.csv
# Format:
# countrycode,countryname
# what this does is not replace the contents of the table, but rather update the specified rows with the names.
# any rows not specified have the countryname reset to be the same as the countrycode.
self.transaction do
self.connection.execute "update #{self.table_name} set countryname = countrycode"
File.open(file, 'r:ISO-8859-1') do |io|
saved_level = ActiveRecord::Base.logger ? ActiveRecord::Base.logger.level : 0
count = 0
ncols = 2
csv = ::CSV.new(io, {encoding: 'ISO-8859-1', headers: false})
csv.each do |row|
raise "file does not have expected number of columns (#{ncols}): #{row.length}" unless row.length == ncols
countrycode = row[0]
countryname = row[1]
stmt = "UPDATE #{self.table_name} SET countryname = #{MaxMindIsp.quote_value(countryname)} WHERE countrycode = #{MaxMindIsp.quote_value(countrycode)}"
self.connection.execute stmt
count += 1
if ActiveRecord::Base.logger and ActiveRecord::Base.logger.level < Logger::INFO
ActiveRecord::Base.logger.debug "... logging updates to #{self.table_name} suspended ..."
ActiveRecord::Base.logger.level = Logger::INFO
end
end
if ActiveRecord::Base.logger
ActiveRecord::Base.logger.level = saved_level
ActiveRecord::Base.logger.debug "updated #{count} records in #{self.table_name}"
end
end # file
end # transaction
end
end
end

View File

@ -1,9 +1,15 @@
class JamRuby::Event < ActiveRecord::Base
attr_accessible :slug, :title, :description, :show_sponser, as: :admin
attr_accessible :slug, :title, :description, :show_sponser, :social_description, as: :admin
validates :slug, uniqueness: true, presence: true
validates :show_sponser, :inclusion => {:in => [true, false]}
before_validation :sanitize_active_admin
def sanitize_active_admin
self.social_description = nil if self.social_description == ''
end
has_many :event_sessions, class_name: 'JamRuby::EventSession'
end

View File

@ -132,7 +132,7 @@ module JamRuby
ActiveRecord::Base.logger.debug "DELETE FROM #{REGIONS_TABLE} returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
sts.check
sts = self.connection.execute "INSERT INTO #{REGIONS_TABLE} (region, countrycode) SELECT DISTINCT region, countrycode FROM #{CITIES_TABLE};"
sts = self.connection.execute "INSERT INTO #{REGIONS_TABLE} (region, regionname, countrycode) SELECT DISTINCT region, region, countrycode FROM #{CITIES_TABLE};"
ActiveRecord::Base.logger.debug "INSERT INTO #{REGIONS_TABLE} returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
sts.check
@ -140,7 +140,7 @@ module JamRuby
ActiveRecord::Base.logger.debug "DELETE FROM #{COUNTRIES_TABLE} returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
sts.check
sts = self.connection.execute "INSERT INTO #{COUNTRIES_TABLE} (countrycode) SELECT DISTINCT countrycode FROM #{REGIONS_TABLE};"
sts = self.connection.execute "INSERT INTO #{COUNTRIES_TABLE} (countrycode, countryname) SELECT DISTINCT countrycode, countrycode FROM #{REGIONS_TABLE};"
ActiveRecord::Base.logger.debug "INSERT INTO #{COUNTRIES_TABLE} returned sts #{sts.cmd_status}" if ActiveRecord::Base.logger
sts.check
end

View File

@ -0,0 +1,56 @@
module JamRuby
class Region < ActiveRecord::Base
self.table_name = 'regions'
def self.get_all(country)
self.where(countrycode: country).order('regionname asc').all
end
def self.import_from_xx_region(countrycode, file)
# File xx_region.csv
# Format:
# region,regionname
# what this does is not replace the contents of the table, but rather update the specifies rows with the names.
# any rows not specified are left alone. the parameter countrycode denote the country of the region (when uppercased)
raise "countrycode (#{MaxMindIsp.quote_value(countrycode)}) is missing or invalid (it must be two characters)" unless countrycode and countrycode.length == 2
countrycode = countrycode.upcase
self.transaction do
self.connection.execute "update #{self.table_name} set regionname = region where countrycode = #{MaxMindIsp.quote_value(countrycode)}"
File.open(file, 'r:ISO-8859-1') do |io|
saved_level = ActiveRecord::Base.logger ? ActiveRecord::Base.logger.level : 0
count = 0
ncols = 2
csv = ::CSV.new(io, {encoding: 'ISO-8859-1', headers: false})
csv.each do |row|
raise "file does not have expected number of columns (#{ncols}): #{row.length}" unless row.length == ncols
region = row[0]
regionname = row[1]
stmt = "UPDATE #{self.table_name} SET regionname = #{MaxMindIsp.quote_value(regionname)} WHERE countrycode = #{MaxMindIsp.quote_value(countrycode)} AND region = #{MaxMindIsp.quote_value(region)}"
self.connection.execute stmt
count += 1
if ActiveRecord::Base.logger and ActiveRecord::Base.logger.level < Logger::INFO
ActiveRecord::Base.logger.debug "... logging updates to #{self.table_name} suspended ..."
ActiveRecord::Base.logger.level = Logger::INFO
end
end
if ActiveRecord::Base.logger
ActiveRecord::Base.logger.level = saved_level
ActiveRecord::Base.logger.debug "updated #{count} records in #{self.table_name}"
end
end # file
end # transaction
end
end
end

View File

@ -153,7 +153,7 @@
context.JK.bindHoverEvents = function ($parent) {
if($parent) {
if(!$parent) {
$parent = $('body');
}

View File

@ -1,5 +1,5 @@
%hr{ class:'w60' }
.landing-band.event
.landing-band.event{'data-event-session' => event_session.id}
= event_session_img(event_session)
%br
%br

View File

@ -1,5 +1,20 @@
- provide(:title, @event.title)
-content_for :social_meta do
%meta{property: 'fb_app_id', content: Rails.application.config.facebook_app_id}
%meta{property: 'og:title', content: 'JamKazam'}
%meta{property: 'og:url', content: request.original_url}
%meta{property: 'og:description', content: @event.social_description || "Play music together over the Internet as if in the same room."}
%meta{property: 'og:image', content: request.protocol + request.host_with_port + image_path("web/logo-256.png")}
%meta{property: 'og:image:width', content: '256'}
%meta{property: 'og:image:height', content: '256'}
%meta{property: 'og:type', content: 'website'}
%meta{property: 'twitter:card', content: 'summary'}
%meta{property: 'twitter:site', content: '@jamkazam'}
%meta{property: 'twitter:title', content: 'JamKazam'}
%meta{property: 'twitter:description',content: @event.social_description || "Play music together over the Internet as if in the same room."}
.landing-content
%h1= @event.title
%p.w60= raw(@event.description)
@ -8,7 +23,7 @@
%h2 ARTIST LINEUP
%br
= render :partial => "event_session", :collection => @event.event_sessions
= render :partial => "event_session", :collection => @event.event_sessions.order('starts_at')
%br{clear:'all'}

View File

@ -115,6 +115,7 @@
$(function () {
var showRecording = new JK.ShowRecording(JK.app);
showRecording.initialize("<%= @claimed_recording.id %>", "<%= @claimed_recording.recording_id %>");
});
</script>
<% end %>

View File

@ -22,7 +22,7 @@
= image_tag 'content/icon_playbutton.png', width:20, height:20, class:'play-icon'
= "{% if(data.feed_item['has_mount?']) { %}"
%audio{preload: 'none'}
%source{src: '{{data.feed_item.music_session.mount.url}}', type: '{{data.feed_item.music_session.mime_type}}'}
%source{src: '{{data.feed_item.music_session.mount.url}}', type: '{{data.feed_item.music_session.mount.mime_type}}'}
= '{% } %}'
%span.session-status
= '{{data.feed_item.helpers.status}}'

View File

@ -12,25 +12,28 @@ class MaxMindManager < BaseManager
city = state = country = nil
unless ip_address.nil? || ip_address !~ /^\d+\.\d+\.\d+\.\d+$/
ActiveRecord::Base.connection_pool.with_connection do |connection|
pg_conn = connection.instance_variable_get("@connection")
ip_as_int = ip_address_to_int(ip_address)
pg_conn.exec("SELECT country, region, city FROM max_mind_geo WHERE ip_start <= $1 AND $2 <= ip_end limit 1", [ip_as_int, ip_as_int]) do |result|
if !result.nil? && result.ntuples > 0
country = result[0]['country']
state = result[0]['region']
city = result[0]['city']
end
end
#ActiveRecord::Base.connection_pool.with_connection do |connection|
# pg_conn = connection.instance_variable_get("@connection")
# ip_as_int = ip_address_to_int(ip_address)
# pg_conn.exec("SELECT country, region, city FROM max_mind_geo WHERE ip_start <= $1 AND $2 <= ip_end limit 1", [ip_as_int, ip_as_int]) do |result|
# if !result.nil? && result.ntuples > 0
# country = result[0]['country']
# state = result[0]['region']
# city = result[0]['city']
# end
# end
#end
ip_as_int = ip_address_to_int(ip_address)
block = GeoIpBlocks.lookup(ip_as_int)
location = block ? GeoIpLocations.lookup(block.locid) : nil
if location
country = location.countrycode
state = location.region
city = location.city
end
end
{
:city => city,
:state => state,
:country => country
}
a = {:city => city, :state => state, :country => country}
end
def self.lookup_isp(ip_address)
@ -53,32 +56,41 @@ class MaxMindManager < BaseManager
end
def self.countries()
ActiveRecord::Base.connection_pool.with_connection do |connection|
pg_conn = connection.instance_variable_get("@connection")
pg_conn.exec("SELECT DISTINCT country FROM max_mind_geo ORDER BY country ASC").map do |tuple|
tuple["country"]
end
end
#ActiveRecord::Base.connection_pool.with_connection do |connection|
# pg_conn = connection.instance_variable_get("@connection")
# pg_conn.exec("SELECT DISTINCT country FROM max_mind_geo ORDER BY country ASC").map do |tuple|
# tuple["country"]
# end
#end
# returns ordered array of Country objects (countrycode, countryname)
Country.get_all.map { |c| c.countrycode }
end
def self.regions(country)
ActiveRecord::Base.connection_pool.with_connection do |connection|
pg_conn = connection.instance_variable_get("@connection")
pg_conn.exec("SELECT DISTINCT region FROM max_mind_geo WHERE country = $1 ORDER BY region ASC", [country]).map do |tuple|
tuple["region"]
end
end
#ActiveRecord::Base.connection_pool.with_connection do |connection|
# pg_conn = connection.instance_variable_get("@connection")
# pg_conn.exec("SELECT DISTINCT region FROM max_mind_geo WHERE country = $1 ORDER BY region ASC", [country]).map do |tuple|
# tuple["region"]
# end
#end
# returns an ordered array of Region objects (region, regionname, countrycode)
Region.get_all(country).map { |r| r.region }
end
def self.cities(country, region)
ActiveRecord::Base.connection_pool.with_connection do |connection|
pg_conn = connection.instance_variable_get("@connection")
pg_conn.exec("SELECT DISTINCT city FROM max_mind_geo WHERE country = $1 AND region = $2 ORDER BY city ASC", [country, region]).map do |tuple|
tuple["city"]
end
end
#ActiveRecord::Base.connection_pool.with_connection do |connection|
# pg_conn = connection.instance_variable_get("@connection")
# pg_conn.exec("SELECT DISTINCT city FROM max_mind_geo WHERE country = $1 AND region = $2 ORDER BY city ASC", [country, region]).map do |tuple|
# tuple["city"]
# end
#end
# returns an ordered array of City (city, region, countrycode)
City.get_all(country, region).map { |c| c.city }
end
@ -116,7 +128,14 @@ class MaxMindManager < BaseManager
]).clear
end
@pg_conn.exec "DELETE FROM cities"
@pg_conn.exec "INSERT INTO cities (city, region, countrycode) SELECT DISTINCT city, region, country FROM max_mind_geo"
@pg_conn.exec "DELETE FROM regions"
@pg_conn.exec "INSERT INTO regions (region, regionname, countrycode) select distinct region, region, countrycode from cities"
@pg_conn.exec "DELETE FROM countries"
@pg_conn.exec "INSERT INTO countries (countrycode, countryname) SELECT DISTINCT countrycode, countrycode FROM regions"
end
private

View File

@ -24,13 +24,25 @@ namespace :db do
JamIsp.import_from_max_mind ENV['file']
end
desc "Import a iso3166 country database (countrycodes and names); run like this: rake db:import_countries file=/path/to/iso3166.csv"
task import_countries: :environment do
Country.import_from_iso3166 ENV['file']
end
desc "Import a region database (regioncode, regionname); run like this: rake db:import_regions countrycode=XX file=/path/to/xx_region.csv"
task import_regions: :environment do
Region.import_from_xx_region(ENV['countrycode'], ENV['file'])
end
desc "Help"
task help: :environment do
puts "bundle exec rake db:import_maxmind_isp file=/path/to/GeoIPISP-142.csv"
puts "bundle exec rake db:import_maxmind_geo file=/path/to/GeoIPCity.csv"
puts "bundle exec rake db:import_geoip_blocks file=/path/to/GeoIPCity-134-Blocks.csv"
puts "bundle exec rake db:import_geoip_locations file=/path/to/GeoIPCity-134-Location.csv"
puts "bundle exec rake db:import_jam_isp file=/path/to/GeoIPISP.csv"
puts "bundle exec rake db:import_maxmind_isp file=/path/to/GeoIPISP-142.csv # geo-142"
puts "bundle exec rake db:import_maxmind_geo file=/path/to/GeoIPCity.csv # geo-139"
puts "bundle exec rake db:import_geoip_blocks file=/path/to/GeoIPCity-134-Blocks.csv # geo-134"
puts "bundle exec rake db:import_geoip_locations file=/path/to/GeoIPCity-134-Location.csv # geo-134"
puts "bundle exec rake db:import_jam_isp file=/path/to/GeoIPISP.csv # geo-124"
puts "bundle exec rake db:import_countries file=/path/to/iso3166.csv # db/geodata"
puts "bundle exec rake db:import_regions countrycode=XX file=/path/to/xx_region.csv # db/geodata, both of them"
end
desc "Create a fake set of maxmind data"

View File

@ -110,5 +110,20 @@ describe "Events", :js => true, :type => :feature, :capybara_feature => true, :s
find('.sessions-page .landing-band', text: band.name) # indication of session landing page
find(".recording-controls[data-music-session=\"#{music_session_history.id}\"]")
# test that it sorts correctly by putting this earlier event first
@event_session2 = FactoryGirl.create(:event_session, event: @event)
@event_session2.starts_at = 4.hours.ago
@event_session2.save!
visit "/events/so_latency"
expect(page).to have_css(".landing-band.event[data-event-session=\"#{@event_session2.id}\"]")
# test that it sorts correctly by putting this later event second
@event_session2.starts_at = 4.hours.from_now
@event_session2.save!
visit "/events/so_latency"
expect(page).to have_css(".landing-band.event[data-event-session=\"#{@event_session.id}\"]")
end
end

View File

@ -20,7 +20,7 @@ describe MaxMindManager do
regions = MaxMindManager.regions("US")
regions.length.should == 4
regions.first.should == "AB"
regions.last.should == "DE" # Based on sort order this will be the top.
regions.last.should == "DE"
end
it "looks up cities successfully" do

View File

@ -31,9 +31,9 @@ describe UserManager do
@user.last_name.should == "smith"
@user.email.should == "userman1@jamkazam.com"
@user.email_confirmed.should be_false
@user.city.should be_nil
@user.state.should be_nil
@user.country.should be_nil
@user.city.should == 'Boston'
@user.state.should == 'MA'
@user.country.should == 'US'
@user.instruments.length.should == 1
@user.subscribe_email.should be_true
@user.signup_token.should_not be_nil
@ -93,8 +93,8 @@ describe UserManager do
signup_confirm_url: "http://localhost:3000/confirm" )
@user.errors.any?.should be_false
@user.city.should == 'City 127'
@user.state.should == 'DE'
@user.city.should == 'Boston'
@user.state.should == 'MA'
@user.country.should == 'US'
end