From 836073633b962466d83855f0fa25782e2bde3638 Mon Sep 17 00:00:00 2001 From: Isaac Canan Date: Fri, 26 Aug 2011 19:04:49 +0000 Subject: [PATCH] [geolocalization] Change Google API version to V3 and implements city and state validations for Brazil case. --- app/controllers/my_profile/maps_controller.rb | 39 +++++++++++++++++++++++++++++++++++++-- app/models/national_region.rb | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ app/models/national_region_type.rb | 5 +++++ app/views/maps/_google_map.rhtml | 304 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------- app/views/maps/edit_location.rhtml | 11 ++++++----- db/migrate/20110726115751_add_national_region_code_to_profiles.rb | 9 +++++++++ db/migrate/20110726121110_create_national_regions.rb | 18 ++++++++++++++++++ db/migrate/20110729130724_national_region_types.rb | 16 ++++++++++++++++ db/migrate/20110729130913_add_region_type_id_to_national_regions.rb | 9 +++++++++ public/stylesheets/application.css | 10 ++++++++++ test/functional/maps_controller_test.rb | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ test/unit/national_region_test.rb | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 541 insertions(+), 92 deletions(-) create mode 100644 app/models/national_region.rb create mode 100644 app/models/national_region_type.rb create mode 100644 db/migrate/20110726115751_add_national_region_code_to_profiles.rb create mode 100644 db/migrate/20110726121110_create_national_regions.rb create mode 100644 db/migrate/20110729130724_national_region_types.rb create mode 100644 db/migrate/20110729130913_add_region_type_id_to_national_regions.rb create mode 100644 test/unit/national_region_test.rb diff --git a/app/controllers/my_profile/maps_controller.rb b/app/controllers/my_profile/maps_controller.rb index dccbca4..1ecac1a 100644 --- a/app/controllers/my_profile/maps_controller.rb +++ b/app/controllers/my_profile/maps_controller.rb @@ -6,16 +6,51 @@ class MapsController < MyProfileController @profile_data = profile if request.post? begin + national_code = nil + country = params[:profile_data][:country] + city = params[:profile_data][:city] + state = params[:profile_data][:state] + + nregion = NationalRegion.validate!(city, state, country) + + if nregion != nil + national_code = nregion.national_region_code + end + + params[:profile_data]["national_region_code"] = national_code + Profile.transaction do if profile.update_attributes!(params[:profile_data]) session[:notice] = _('Address was updated successfully!') redirect_to :action => 'edit_location' end end - rescue - flash[:error] = _('Address could not be saved.') + rescue Exception => exc + + flash[:error] = exc.message + end end end + def search_city + + term = params[:term]; + + regions = NationalRegion.search_city(term + "%", true).map {|r|{ :label => r.city , :category => r.state}} + + render :json => regions + + end + + def search_state + + term = params[:term]; + + regions = NationalRegion.search_state(term + "%", true).map {|r|{ :label => r.state}} + + render :json => regions + + end + end diff --git a/app/models/national_region.rb b/app/models/national_region.rb new file mode 100644 index 0000000..0b50079 --- /dev/null +++ b/app/models/national_region.rb @@ -0,0 +1,71 @@ +class NationalRegion < ActiveRecord::Base + + def self.search_city(city_name, like = false, state = nil) + + operator = "=" + find_return = :first + adtional_contions = ""; + + if like + operator = "like" + find_return = :all + end + + if state + adtional_contions = " AND nr.name = :state " + end + + conditions = ["national_regions.name #{operator} :name AND + national_regions.national_region_type_id = :type" + adtional_contions, + {:name => city_name , + :type => NationalRegionType::CITY, + :state => state}]; + + region = NationalRegion.find(find_return, + :select => "national_regions.name as city, nr.name as state, national_regions.national_region_code", + :conditions => conditions, + :joins => "LEFT JOIN national_regions as nr ON national_regions.parent_national_region_code = nr.national_region_code", + :limit => 10 + ) + return region + end + + def self.search_state(state_name, like = false) + operator = "=" + find_return = :first + + if like + operator = "like" + find_return = :all + end + + conditions = ["national_regions.name #{operator} :name AND + national_regions.national_region_type_id = :type", + {:name => state_name, + :type => NationalRegionType::STATE}]; + + region = NationalRegion.find(find_return, + :select => "national_regions.name as state, national_regions.national_region_code", + :conditions => conditions, + :limit => 10 + ) + return region + end + + def self.validate!(city, state, country) + + if(country == "BR") + + nregion = NationalRegion.search_city(city, false, state); + + if nregion == nil + raise _('Invalid city or state name.') + end + + end + + return nregion + + end + +end diff --git a/app/models/national_region_type.rb b/app/models/national_region_type.rb new file mode 100644 index 0000000..ae3f1e6 --- /dev/null +++ b/app/models/national_region_type.rb @@ -0,0 +1,5 @@ +class NationalRegionType < ActiveRecord::Base + COUNTRY = 1 + STATE = 2 + CITY = 3 +end diff --git a/app/views/maps/_google_map.rhtml b/app/views/maps/_google_map.rhtml index 5a73ec8..ca4711e 100644 --- a/app/views/maps/_google_map.rhtml +++ b/app/views/maps/_google_map.rhtml @@ -1,6 +1,7 @@ -<%= content_tag('script', '', :src => GoogleMaps.api_url(profile.default_hostname), :type => 'text/javascript') %> +<%= content_tag('script', '', :src => "http://maps.googleapis.com/maps/api/js?sensor=false", :type => 'text/javascript') %> + + diff --git a/app/views/maps/edit_location.rhtml b/app/views/maps/edit_location.rhtml index 13ca1a9..6ddce29 100644 --- a/app/views/maps/edit_location.rhtml +++ b/app/views/maps/edit_location.rhtml @@ -1,5 +1,7 @@

<%= _('Location') %>

- +
+ <%= flash[:error] %> +
<% form_for :profile_data, :url => {:action => 'edit_location'} do |f| %>
@@ -9,26 +11,25 @@ <%= optional_field(profile, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code))) %> <%= optional_field(profile, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address))) %> <% button_bar do %> - <%= button_to_function :search, _('Locate in the map'), "getAddress(null, getAddressData())", :title => _("Locate the address informed above in the map below (note that you'll probably need to adjust the marker to get a precise position)") %> + <%= button_to_function :search, _('Locate in the map'), "codeAddress()", :title => _("Locate the address informed above in the map below (note that you'll probably need to adjust the marker to get a precise position)") %> <%= submit_button 'save', _('Save') %> <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> <% end %>
-

<%= f.hidden_field(:lat) %> <%= f.hidden_field(:lng) %> - - + <% button_bar do %> <%= submit_button 'save', _('Save') %> <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> <% end %> + <% end %> diff --git a/db/migrate/20110726115751_add_national_region_code_to_profiles.rb b/db/migrate/20110726115751_add_national_region_code_to_profiles.rb new file mode 100644 index 0000000..c593b78 --- /dev/null +++ b/db/migrate/20110726115751_add_national_region_code_to_profiles.rb @@ -0,0 +1,9 @@ +class AddNationalRegionCodeToProfiles < ActiveRecord::Migration + def self.up + add_column :profiles, :national_region_code, :string, :null => true + end + + def self.down + remove_column :profiles, :national_region_code + end +end diff --git a/db/migrate/20110726121110_create_national_regions.rb b/db/migrate/20110726121110_create_national_regions.rb new file mode 100644 index 0000000..9cc3c6a --- /dev/null +++ b/db/migrate/20110726121110_create_national_regions.rb @@ -0,0 +1,18 @@ +class CreateNationalRegions < ActiveRecord::Migration + def self.up + create_table :national_regions do |t| + t.string :name + t.string :national_region_code + t.string :parent_national_region_code + + t.timestamps + end + + add_index(:national_regions, :national_region_code, {:name => "code_index"}) + add_index(:national_regions, :name, {:name => "name_index"}) + end + + def self.down + drop_table :national_regions + end +end diff --git a/db/migrate/20110729130724_national_region_types.rb b/db/migrate/20110729130724_national_region_types.rb new file mode 100644 index 0000000..93c937c --- /dev/null +++ b/db/migrate/20110729130724_national_region_types.rb @@ -0,0 +1,16 @@ +class NationalRegionTypes < ActiveRecord::Migration + def self.up + create_table :national_region_types do |t| + t.string :name + end + + NationalRegionType.create :name => "Country" + NationalRegionType.create :name => "State" + NationalRegionType.create :name => "City" + + end + + def self.down + drop_table :national_region_types + end +end diff --git a/db/migrate/20110729130913_add_region_type_id_to_national_regions.rb b/db/migrate/20110729130913_add_region_type_id_to_national_regions.rb new file mode 100644 index 0000000..003858c --- /dev/null +++ b/db/migrate/20110729130913_add_region_type_id_to_national_regions.rb @@ -0,0 +1,9 @@ +class AddRegionTypeIdToNationalRegions < ActiveRecord::Migration + def self.up + add_column :national_regions, :national_region_type_id, :integer, :null => false + end + + def self.down + remove_column :national_regions, :national_region_type_id + end +end diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index c45adf5..8f011c4 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -5640,3 +5640,13 @@ h1.page-title.no-boxes small { .clearfix:after { clear: both; } + +/* AutoComplete*/ +.formfield input.ui-autocomplete-loading { background: url('/images/loading-small.gif') right center no-repeat, url("../images/input-bg.gif") no-repeat left top; } + +.ui-autocomplete-category { + font-weight: bold; + padding: .2em .4em; + margin: .8em 0 .2em; + line-height: 1.5; +} diff --git a/test/functional/maps_controller_test.rb b/test/functional/maps_controller_test.rb index 437abc2..5639b3c 100644 --- a/test/functional/maps_controller_test.rb +++ b/test/functional/maps_controller_test.rb @@ -22,6 +22,31 @@ class MapsControllerTest < ActionController::TestCase assert_equal 'new address', Profile['test_profile'].address end + should 'save profile national_region_code' do + + national_region_code = '355030' + city = 'Santo Afonso' + state = 'Mato Grosso' + + parent_region = fast_create(NationalRegion, :name => state, + :national_region_code => '35', + :national_region_type_id => NationalRegionType::STATE) + + fast_create(NationalRegion, :name => city, + :national_region_code => national_region_code, + :national_region_type_id => NationalRegionType::CITY, + :parent_national_region_code => parent_region.national_region_code) + + post :edit_location, :profile => profile.identifier, :profile_data => { + :address => 'new address', + :country => 'BR', + :city => city, + :state => state + } + + assert_equal national_region_code, Profile['test_profile'].national_region_code + end + should 'back when update address fail' do Profile.any_instance.stubs(:update_attributes!).returns(false) post :edit_location, :profile => profile.identifier, :profile_data => { 'address' => 'new address' } @@ -45,13 +70,47 @@ class MapsControllerTest < ActionController::TestCase assert_tag :tag => 'input', :attributes => { :name => 'profile_data[city]' } end - should 'add script tag for google maps' do - domain = fast_create(Domain, :name => 'domain-with-key', :google_maps_key => 'DOMAIN_KEY') - profile.preferred_domain = domain - profile.save! + should 'autocomplete search_city' do + + city = 'Santo Afonso' + state = 'Mato Grosso' + + parent_region = fast_create(NationalRegion, :name => state, + :national_region_code => '35', + :national_region_type_id => NationalRegionType::STATE) + + fast_create(NationalRegion, :name => city, + :national_region_code => '355030', + :national_region_type_id => NationalRegionType::CITY, + :parent_national_region_code => parent_region.national_region_code) + + get :search_city, :term => "San", :profile => profile.identifier + + json_response = ActiveSupport::JSON.decode(@response.body) + + label = json_response[0]['label'] + category = json_response[0]['category'] + + assert_equal city, label + assert_equal state, category + end + + should 'autocomplete search_state' do + + state = 'Mato Grosso do Sul' + + + fast_create(NationalRegion, :name => state, + :national_region_code => '36', + :national_region_type_id => NationalRegionType::STATE) + + + get :search_state, :term => "Mat", :profile => profile.identifier + + json_response = ActiveSupport::JSON.decode(@response.body) - get 'edit_location', :profile => profile.identifier + label = json_response[0]['label'] - assert_tag :tag => 'script', :attributes => { :src => 'http://maps.google.com/maps?file=api&v=2&key=DOMAIN_KEY'} + assert_equal state, label end end diff --git a/test/unit/national_region_test.rb b/test/unit/national_region_test.rb new file mode 100644 index 0000000..3130481 --- /dev/null +++ b/test/unit/national_region_test.rb @@ -0,0 +1,70 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class NationalRegionTest < ActiveSupport::TestCase + + should 'search_city especific city' do + city_name = "Santos" + + new_region = fast_create(NationalRegion, :name => city_name, + :national_region_code => '355030', + :national_region_type_id => NationalRegionType::CITY) + + found_region = NationalRegion.search_city(city_name) + + assert_equal new_region.name, found_region.city + assert_equal new_region.national_region_code, found_region.national_region_code + end + + should 'search_city like cities' do + city_names = [ "Santo Afonso", "Santo Antonio", "Santo Augusto" ] + new_regions = [] + + for i in 0..city_names.length + new_regions << fast_create(NationalRegion, :name => city_names[i], + :national_region_code => '355030', + :national_region_type_id => NationalRegionType::CITY) + end + + found_regions = NationalRegion.search_city('Santo %', true) + + assert !(found_regions.length != 3) + + found_regions.each do |region| + assert city_names.find_index(region.city) >= 0 + end + + end + + should 'search_city especific state' do + state_name = "Santa Catarina" + + new_region = fast_create(NationalRegion, :name => state_name, + :national_region_code => '22', + :national_region_type_id => NationalRegionType::STATE) + + found_region = NationalRegion.search_state(state_name) + + assert_equal new_region.name, found_region.state + assert_equal new_region.national_region_code, found_region.national_region_code + end + + should 'search_city like states' do + state_names = [ "Rio de Janeiro", "Rio Grande do Norte", "Rio Grande do Sul" ] + new_regions = [] + + for i in 0..state_names.length + new_regions << fast_create(NationalRegion, :name => state_names[i], + :national_region_code => '35', + :national_region_type_id => NationalRegionType::STATE) + end + + found_regions = NationalRegion.search_state('Rio %', true) + + assert !(found_regions.length != 3) + + found_regions.each do |region| + assert state_names.find_index(region.state) >= 0 + end + + end +end -- libgit2 0.21.2