From 6768472528ecb88ebb69a2088fd3c12ebfcddd82 Mon Sep 17 00:00:00 2001 From: Mike Slemmer Date: Sat, 15 Dec 2012 12:17:41 -0800 Subject: [PATCH] regions and cities requests plus tests --- .../api_maxmind_requests_controller.rb | 23 ++++++++++++ config/routes.rb | 4 +++ lib/managers/max_mind_manager.rb | 29 ++++++++++++--- spec/managers/maxmind_manager_spec.rb | 36 +++++++++++++++++++ spec/managers/user_manager_spec.rb | 4 +-- 5 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 app/controllers/api_maxmind_requests_controller.rb create mode 100644 spec/managers/maxmind_manager_spec.rb diff --git a/app/controllers/api_maxmind_requests_controller.rb b/app/controllers/api_maxmind_requests_controller.rb new file mode 100644 index 000000000..b9b65254e --- /dev/null +++ b/app/controllers/api_maxmind_requests_controller.rb @@ -0,0 +1,23 @@ +class ApiMaxMindRequestsController < ApiController + + respond_to :json + + def regions + regions = MaxMindManager.regions(params[:country]) + if regions && regions.length > 0 + render :json => { :regions => regions }, :status => 200 + else + render :json => { :message => "Unrecognized Country" }, :status => 404 + end + end + + def cities + cities = MaxMindManager.cities(params[:country], params[:region]) + if cities && cities.length > 0 + render :json => { :cities => cities }, :status => 200 + else + render :json => { :message => "Unrecognzied country or region" }, :status => 404 + end + end + +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 1bb4811f4..66951c294 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -150,5 +150,9 @@ SampleApp::Application.routes.draw do match '/join_requests/:id' => 'api_join_requests#delete', :via => :delete match '/join_requests' => 'api_join_requests#create', :via => :post match '/join_requests' => 'api_join_requests#index', :via => :get + + # Location lookups + match '/regions' => 'api_maxmind_requests#regions', :via => :get + match '/cities' => 'api_maxmind_requests#cities', :via => :get end end diff --git a/lib/managers/max_mind_manager.rb b/lib/managers/max_mind_manager.rb index f5546f830..68b55a707 100644 --- a/lib/managers/max_mind_manager.rb +++ b/lib/managers/max_mind_manager.rb @@ -33,6 +33,27 @@ class MaxMindManager < BaseManager 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 WHERE country = $1 ORDER BY region ASC", [country]).map do |tuple| + tuple["region"] + end + end + 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 WHERE country = $1 AND region = $2 ORDER BY city ASC", [country, region]).map do |tuple| + tuple["city"] + end + end + end + + + # Do this in a transaction so there's no partial import. def import_database(filename) @@ -59,6 +80,7 @@ class MaxMindManager < BaseManager end end + # Note that there's one big country, and then two cities in each region. def create_phony_database() clear_table (0..255).each do |top_octet| @@ -66,14 +88,13 @@ class MaxMindManager < BaseManager [ self.class.ip_address_to_int("#{top_octet}.0.0.0"), self.class.ip_address_to_int("#{top_octet}.255.255.255"), - "Country #{top_octet}", - "Region #{top_octet}", + "Country", + "Region #{(top_octet / 2).floor}", "City #{top_octet}" - ]).clear + ]).clear end end - private # Make an IP address fit in a signed int. Just divide it by 2, as the least significant part diff --git a/spec/managers/maxmind_manager_spec.rb b/spec/managers/maxmind_manager_spec.rb new file mode 100644 index 000000000..a4555638d --- /dev/null +++ b/spec/managers/maxmind_manager_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +# these tests avoid the use of ActiveRecord and FactoryGirl to do blackbox, non test-instrumented tests +describe MaxMindManager do + + + before(:each) do + @maxmind_manager = MaxMindManager.new(:conn => @conn) + end + + it "looks up regions successfully" do + MaxMindManager.active_record_transaction do |manager| + manager.create_phony_database() + end + + regions = MaxMindManager.regions("Country") + regions.length.should == 128 + regions.first.should == "Region 0" + regions.last.should == "Region 99" # Based on sort order this will be the top. + end + + it "looks up cities successfully" do + MaxMindManager.active_record_transaction do |manager| + manager.create_phony_database() + end + + cities = MaxMindManager.cities("Country", "Region 1") + cities.length.should == 2 + cities.first.should == "City 2" + cities.last.should == "City 3" + end + + +end + + diff --git a/spec/managers/user_manager_spec.rb b/spec/managers/user_manager_spec.rb index 894df7c8a..762d9b621 100644 --- a/spec/managers/user_manager_spec.rb +++ b/spec/managers/user_manager_spec.rb @@ -55,8 +55,8 @@ describe UserManager do @user.errors.any?.should be_false @user.city.should == 'City 127' - @user.state.should == 'Region 127' - @user.country.should == 'Country 127' + @user.state.should == 'Region 63' + @user.country.should == 'Country' end