From 324531914cfb3e160f9af5909aa5020d4b7dfcd3 Mon Sep 17 00:00:00 2001 From: Harry Levine Date: Thu, 20 Jul 2017 20:08:09 -0600 Subject: [PATCH 1/6] Adds :state column to User --- app/controllers/api/v1/users_controller.rb | 2 +- db/migrate/20170720215043_add_state_to_user.rb | 5 +++++ db/schema.rb | 3 ++- test/factories/users.rb | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20170720215043_add_state_to_user.rb diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb index 3d481fa5..500ce84e 100644 --- a/app/controllers/api/v1/users_controller.rb +++ b/app/controllers/api/v1/users_controller.rb @@ -42,7 +42,7 @@ def by_location private def user_params - params.require(:user).permit(:email, :zip, :password, :first_name, :last_name, :mentor, :slack_name, :verified) + params.require(:user).permit(:email, :zip, :password, :first_name, :last_name, :mentor, :slack_name, :verified, :state) end end end diff --git a/db/migrate/20170720215043_add_state_to_user.rb b/db/migrate/20170720215043_add_state_to_user.rb new file mode 100644 index 00000000..4bd96758 --- /dev/null +++ b/db/migrate/20170720215043_add_state_to_user.rb @@ -0,0 +1,5 @@ +class AddStateToUser < ActiveRecord::Migration[5.0] + def change + add_column :users, :state, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 1f994fa1..6b5e75d6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170701194821) do +ActiveRecord::Schema.define(version: 20170720215043) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -154,6 +154,7 @@ t.string "timezone" t.text "bio" t.boolean "verified", default: false, null: false + t.string "state" t.index ["email"], name: "index_users_on_email", unique: true, using: :btree t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree end diff --git a/test/factories/users.rb b/test/factories/users.rb index bc2c8feb..4877285c 100644 --- a/test/factories/users.rb +++ b/test/factories/users.rb @@ -13,6 +13,7 @@ timezone 'EST' mentor false verified false + state { Faker::Address.state_abbr } factory :mentor do mentor true From fbfa4c2860e1899e024c63e508d603b188d914dd Mon Sep 17 00:00:00 2001 From: Harry Levine Date: Thu, 20 Jul 2017 20:08:32 -0600 Subject: [PATCH 2/6] Adds make command for rake db:rollback --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index f1ae74a5..872316a4 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,10 @@ db_create: db_migrate: docker-compose run ${RAILS_CONTAINER} rake db:migrate +.PHONY: db_rollback +db_rollback: + docker-compose run ${RAILS_CONTAINER} rake db:rollback + .PHONY: test test: bg docker-compose run operationcode-psql bash -c "while ! psql --host=operationcode-psql --username=postgres -c 'SELECT 1'; do sleep 5; done;" From 1ab6184a0ab93a5ea838bc8ce18f5d0ea692be1c Mon Sep 17 00:00:00 2001 From: Harry Levine Date: Thu, 20 Jul 2017 20:09:25 -0600 Subject: [PATCH 3/6] =?UTF-8?q?Saves=20user=E2=80=99s=20lat,=20long,=20and?= =?UTF-8?q?=20state=20abbreviation=20on=20before=5Fsave?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/user.rb | 9 ++++++++- test/models/user_test.rb | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index be299c94..6445a8ef 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,7 +3,14 @@ class User < ApplicationRecord # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable - geocoded_by :zip + + geocoded_by :zip do |user, results| + if geocoded_object = results.first + user.latitude = geocoded_object.latitude + user.longitude = geocoded_object.longitude + user.state = geocoded_object.state_code + end + end # These attributes are what we send to sendgrid as custom fields SENDGRID_ATTRIBUTES = %w[first_name last_name email] diff --git a/test/models/user_test.rb b/test/models/user_test.rb index 7e627916..b2dbb47d 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb @@ -41,6 +41,7 @@ def setup u.update_attributes(zip: '80203') assert_equal 20.7143528, u.latitude assert_equal -174.0059731, u.longitude + assert_equal 'CO', u.state end test 'only geocodes if zip is updated' do From 20b5b8018fe22217f8cfefdcdc58736ad977e3ec Mon Sep 17 00:00:00 2001 From: Harry Levine Date: Thu, 20 Jul 2017 20:10:30 -0600 Subject: [PATCH 4/6] Rake task to set eligible user.state based on user.zip --- lib/tasks/users.rake | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 lib/tasks/users.rake diff --git a/lib/tasks/users.rake b/lib/tasks/users.rake new file mode 100644 index 00000000..04ef1a04 --- /dev/null +++ b/lib/tasks/users.rake @@ -0,0 +1,34 @@ +namespace :users do + desc "Sets the user's :state based on user's :zip, for any any where user.state == nil" + task populate_states: :environment do + # https://developers.google.com/maps/documentation/geocoding/usage-limits + GEOCODING_DAILY_MAX = 2500 + GEOCODING_PER_S_MAX = 50 + + users = User.where.not(latitude: nil, longitude: nil).where(state: nil).limit(GEOCODING_DAILY_MAX) + user_count = users.count + + return "0 eligible users to be updated" unless users.present? + p "#{user_count} users are eligible to be updated." + + users.in_batches(of: GEOCODING_PER_S_MAX).each_with_index do |batch, batch_index| + batch.each_with_index do |user, index| + p "Updating #{(batch_index * GEOCODING_PER_S_MAX) + index + 1} of #{user_count}" + + begin + results = Geocoder.search([user.latitude, user.longitude]).try(:first) + + user.update! state: results.state_code + rescue => e + p "When adding the :state for User id #{user.id}, experienced this error: #{e}" + Rails.logger.info "When adding the :state for User id #{user.id}, experienced this error: #{e}" + end + end + + sleep 2 + end + + remaining = User.where.not(latitude: nil, longitude: nil).where(state: nil).count + p "#{remaining} users left to be updated. Task can be reran in 24 hours." + end +end From 3537de9a182848e9abe8f1c3f291984009d5d350 Mon Sep 17 00:00:00 2001 From: Harry Levine Date: Thu, 20 Jul 2017 20:22:57 -0600 Subject: [PATCH 5/6] Raises error if no geocoding results are returned --- lib/tasks/users.rake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/tasks/users.rake b/lib/tasks/users.rake index 04ef1a04..12245463 100644 --- a/lib/tasks/users.rake +++ b/lib/tasks/users.rake @@ -18,6 +18,8 @@ namespace :users do begin results = Geocoder.search([user.latitude, user.longitude]).try(:first) + raise "Could not geocode User id #{user.id}" unless results.present? + user.update! state: results.state_code rescue => e p "When adding the :state for User id #{user.id}, experienced this error: #{e}" From 6393bdd65d5c205722a04d30cb83ef953132c7b3 Mon Sep 17 00:00:00 2001 From: Harry Levine Date: Thu, 20 Jul 2017 20:24:48 -0600 Subject: [PATCH 6/6] Fixes CC issue with assignment in conditional --- app/models/user.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 6445a8ef..f82ed42a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,7 +5,9 @@ class User < ApplicationRecord :recoverable, :rememberable, :trackable, :validatable geocoded_by :zip do |user, results| - if geocoded_object = results.first + geocoded_object = results.first + + if geocoded_object.present? user.latitude = geocoded_object.latitude user.longitude = geocoded_object.longitude user.state = geocoded_object.state_code