Was Geocoder successful? - geokit

Geokit has the helpful functionality:
g = Geokit::Geocoders::GoogleGeocoder.geocode [address_1, address_2, city, zip_code, state, country].compact.join(', ')
if g.success == true
...
Can the Geocoder gem return a true somehow if Google successfully geocoded the address given?

Related

register custom user with django allauth

I have a custom User model:
class User(AbstractUser):
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
phone_number = models.CharField(validators=[phone_regex], max_length=17, blank=False, null=False) # validators should be a list
email = models.EmailField(blank=False, null=False)
points = models.PositiveIntegerField(default=0)
REQUIRED_FIELDS = ['phone_number', 'email']
objects = UserManager()
With his UserManager:
class UserManager(BaseUserManager):
def create_user(self, username, email, phone_number, password):
if not username:
raise ValueError('Users must have a username')
if not email:
raise ValueError('Users must have an email address')
if not phone_number:
raise ValueError('Users must have a phone_number')
user = self.model(
username,
phone_number,
email=self.normalize_email(email)
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email, phone_number, password):
if not username:
raise ValueError('Users must have a username')
if not email:
raise ValueError('Users must have an email address')
if not phone_number:
raise ValueError('Users must have a phone_number')
user = self.create_user(
username,
phone_number,
email=self.normalize_email(email)
)
user.set_password(password)
user.is_superuser = True
user.save(using=self._db)
return user
I am using allauth to register users, but when I register a new user in /rest-auth/registration (POST) the fields a still the default ones (username, email, password1, password2) instead of adding phone_number for example. How can I do to allow more (or delete some) fields to register a new user?
=== EDIT ===
I also have In my settings.py
AUTH_USER_MODEL = 'userTest.User'
ACCOUNT_SIGNUP_FORM_CLASS = 'userTest.forms.RegisterForm'
and in forms.py a form just for testing but it doesn't seem to work:
class RegisterForm(forms.Form):
phone_number = forms.CharField(label='Phone Number', max_length=17)
first_name = forms.CharField()
def signup(self, request, user):
user.phone_number = self.cleaned_data['phone_number']
user.first_name = self.cleaned_data['first_name']
user.save()
You have to extend AbstaractBaseUser
from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager)
class User(AbstractBaseUser):
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
phone_number = models.CharField(validators=[phone_regex], max_length=17, blank=False, null=False) # validators should be a list
email = models.EmailField(blank=False, null=False)
points = models.PositiveIntegerField(default=0)
REQUIRED_FIELDS = ['phone_number', 'email']
objects = UserManager()

SQL "IN" as LINQ query using method syntax

I have a set of related tables that I am trying to return a result set for and I just can't get the syntax quite right to get the results I want.
I am trying to return a list of countries (United States being the only one expected right now) with appropriate states. The "appropriate" requirement is that I only want to return the states under the countries that are represented by one of our clients....ie....if we have 3 clients, 2 in Texas and 1 in OK, I need the query to return "United States (with only Texas and OK...not the other 48 states where we don't have clients).
I can get the query to return only the United States, but it returns ALL states, not just the ones I am after. This is an example of the query that I "want" to run....NOTE: FirstAdminDivision table = states table.
select * from Country c
inner join FirstAdminDivision f on f.CountryId = c.CountryId
where f.FirstAdminDivisionId IN
(
select f2.FirstAdminDivisionId from Company C
inner join [Address] a on a.AddressId = c.AddressId
inner join City cty on cty.CityId = a.CityId
inner join FirstAdminDivision f2 on f2.FirstAdminDivisionId = cty.FirstAdminDivisionId
)
This is the code I currently have (which is as close as I have been able to get) that returns the US only with all states. The "ids" list contains only Texas and OK like I would expect, so I think they issue lies in the where in the main select.
IQueryable<int> innerQ = base.Context.Set<FirstAdminDivision>().Where(x => x.Cities.Any(y => y.Addresses.Any(z => z.Companies.Any()))).Select(x => x.FirstAdminDivisionId);
List<int> ids = innerQ.ToList();
IQueryable<ICountryModel> q2 = base.Context.Set<Country>()
.Include(x => x.FirstAdminDivisions)
.Where(x => x.FirstAdminDivisions.Where(y => innerQ.Contains(y.FirstAdminDivisionId)).Any())
.Select(x => new CountryModel
{
Abbreviation = x.Abbreviation,
CountryId = x.CountryId,
Name = x.Name,
UrlDisplay = x.UrlDisplay,
FirstAdminDivisions = x.FirstAdminDivisions.Select(y => new FirstAdminDivisionModel
{
Abbreviation = y.Abbreviation,
Name = y.Name,
UrlDisplay = y.UrlDisplay
}).ToList()
});
Any help pointing out what I am missing/doing wrong would be greatly appreciated.
Well basically i would use your first query as the base query instead of all the countries and instead of returning a list of ints i would want it to return a list of FirstAdminDivision objects.
So in this case you would have two objects in that list OK and Texas. And in this case you also should have the country available since you say that FirstAdminDivision has the country as a property
Then from that list i would include country object so you can group those two state objects by country. And from that build your model using the key, country, and then the list of states.
Something like this:
IQueryable<ICountryModel> countriesWithStates = base.Context.Set<FirstAdminDivision>()
.Where(x => x.Cities.Any(y => y.Addresses.Any(z => z.Companies.Any())))
.Include(x => x.Country)
.GroupBy(x => x.Country, y=>y, (countryKey, states) => new { Country = countryKey, States = states.ToList() })
.Select(x => new CountryModel
{
Abbreviation = x.Country.Abbreviation,
CountryId = x.Country.CountryId,
Name = x.Country.Name,
UrlDisplay = x.Country.UrlDisplay,
FirstAdminDivisions = x.States.Select(y => new FirstAdminDivisionModel
{
Abbreviation = y.Abbreviation,
Name = y.Name,
UrlDisplay = y.UrlDisplay
}).ToList()
});

Find coordinates for my database's address column

I have my own database that includes: address, lat, long, name.
I have all the addresses that I want without their coordinates. Is there a way to find the coordinates in order to use them as markers on my active map?
In other words I want something to batch?! geocode my addresses that are already in to my database.
Thank you very much
Edited:
def index
if params[:search].present?
#locations = Location.near(params[:search], 20, :order => :distance)
else
#locations = Location.all
#locations.each do |l|
if l.latitude.nil?
new_location = "#{l.address}"
s = Geocoder.search(new_location)
l.latitude = s[0].latitude
l.longitude = s[0].longitude
l.save
end
end
end
This is what I have, but it updates only my first address on the database.
Check out the gmaps4rails gem at https://github.com/apneadiving/Google-Maps-for-Rails
Here's what I use in the model one of my apps:
acts_as_gmappable lat: 'latitude', lng: 'longitude',
process_geocoding: :geocode?,
address: :full_address,
msg: "Sorry, not even Google could figure out where that is"
Oh, and here's my geocode? method:
def geocode?
latitude.blank? || longitude.blank?
end
So when the model's latitude and/or longitude are nil, gmaps4rails automatically does a lookup and fills in the entries.

Using Geocoder, is there a way to save out the street name, city and zip to seperate columns?

I'm in the process of switching my app to use geocoder. In my places table I have columns for address, lat, lng, street_address, city & zip. Using geocoder I'm happily able to fill lat, lng & address columns after validation with with the following in my places model
attr_accessible :address, :lat, :lng
geocoded_by :address, :latitude => :lat, :longitude => :lng
after_validation :geocode, :if => :address_changed?
Is there a way to also have geocoder add the street name, city and zip to three other, separate columns?
I'm still newish to rails so I missed this at first, but hope this helps someone else.
in my model
geocoded_by :address do |obj,results|
if geo = results.first
obj.city = geo.city
obj.lat = geo.latitude
obj.lng = geo.longitude
obj.zip = geo.postal_code
obj.state = geo.state
obj.country = geo.country_code
end
end
and in my view
#tonic.address = params[:address]

Integrating facebook login with omniauth on rails

I am using Railscast Episode # 250 to implement authentication from scratch. However, now I want to implement Facebook login. From googling I've found that OmniAuth and Devise are the prime contenders to do this in Rails
However, this example page is confusing me: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
It states:
With Rails 3.0.3, use this in your Gemfile instead if rails is having
trouble loading oauth core:
gem "omniauth"
Next, you need to declare the provider in your
config/initializers/devise.rb:
config.omniauth :facebook, "APP_ID", "APP_SECRET"
Question
Are omniauth and devise interelated?
What should I do to implement Facebook login in my authentication based on Railscast 250
In your specific case you can think that Devise allows your application to authenticate users using a form (ex: by using an email and password) or an authentication token, Omniauth allows your application to "speak" to the Facebook servers to authenticate a user. In other words Omniauth sits on top of Devise and extends the number of ways your user can authenticate.
To implement Facebook login you need to:
0) configure devise: just follow this: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
1) expose a link in your view that when clicked by the user will tell Omniauth to start "speaking" to the Facebook server.
=link_to image_tag("facebook_64.png", :size => "64x64", :alt => "Facebook"), user_omniauth_authorize_path(:facebook, :display=>"dialog"), :title=>"Facebook"
2) At one point the Facebook server will call you app so you have to implement a controller to respond to Facebook
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
before_filter { #omniauth_hash = env["omniauth.auth"] }
# This method is responsible to create a registration_hash given an
# omniaauth_hash
# schama: https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema
def self.build_registration_hash(omniauth_hash={})
if (omniauth_hash["provider"].downcase.eql?("facebook"))
provider = "facebook"
# catch any excpetions thrown by code just to make sure we can continue even if parts of the omnia_has are missing
begin
first_name = omniauth_hash['user_info']['first_name']
last_name = omniauth_hash['user_info']['last_name']
sex = omniauth_hash.fetch('extra', {}).fetch('user_hash',{})['gender']
birthday = Date.strptime(omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['birthday'],'%m/%d/%Y') if omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['birthday']
if omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['timezone']
utc_offset_in_hours = (omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['timezone']).to_i
time_zone = (ActiveSupport::TimeZone[utc_offset_in_hours]).name
else
time_zone = nil
end
locale = omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['locale']
home_town = omniauth_hash.fetch('extra', {}).fetch('user_hash', {}).fetch('location', {})['name']
if omniauth_hash.fetch('user_info', {})['image']
photo_url = (omniauth_hash.fetch('user_info', {})['image']).gsub("=square","=large") #http://graph.facebook.com/531564247/picture?type=square
else
photo_url = nil
end
rescue => ex
logger.error("Error while parsing facebook auth hash: #{ex.class}: #{ex.message}")
sex = nil
birthday = nil
time_zone = nil
locale = nil
home_town = nil
photo_url = nil
end
elsif omniauth_hash['uid'].downcase.include?("google.com")
provider = "google"
if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name']
first_name = omniauth_hash['user_info']['first_name']
last_name = omniauth_hash['user_info']['last_name']
elsif omniauth_hash['user_info']['name']
first_name = omniauth_hash['user_info']['name'].split(' ')[0]
last_name = omniauth_hash['user_info']['name'].split(' ')[1]
else
first_name = nil
last_name = nil
end
sex = nil
birthday = nil
time_zone = nil
locale = nil
home_town = nil
photo_url = nil
elsif omniauth_hash['uid'].downcase.include?("yahoo.com")
provider = "yahoo"
if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name']
first_name = omniauth_hash['user_info']['first_name']
last_name = omniauth_hash['user_info']['last_name']
elsif omniauth_hash['user_info']['name']
first_name = omniauth_hash['user_info']['name'].split(' ')[0]
last_name = omniauth_hash['user_info']['name'].split(' ')[1]
else
first_name = nil
last_name = nil
end
sex = nil
birthday = nil
time_zone = nil
locale = nil
home_town = nil
photo_url = nil
elsif omniauth_hash['uid'].downcase.include?("aol.com")
if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name']
first_name = omniauth_hash['user_info']['first_name']
last_name = omniauth_hash['user_info']['last_name']
elsif omniauth_hash['user_info']['name']
first_name = omniauth_hash['user_info']['name'].split(' ')[0]
last_name = omniauth_hash['user_info']['name'].split(' ')[1]
else
first_name = nil
last_name = nil
end
provider = "aol"
sex = nil
birthday = nil
time_zone = nil
locale = nil
home_town = nil
photo_url = nil
else
provider = "open_id"
if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name']
first_name = omniauth_hash['user_info']['first_name']
last_name = omniauth_hash['user_info']['last_name']
elsif omniauth_hash['user_info']['name']
first_name = omniauth_hash['user_info']['name'].split(' ')[0]
last_name = omniauth_hash['user_info']['name'].split(' ')[1]
else
first_name = nil
last_name = nil
end
sex = nil
birthday = nil
time_zone = nil
locale = nil
home_town = nil
photo_url = nil
end
h = {
:provider => provider,
:email => omniauth_hash['user_info']['email'],
:profile_attributes => {
:first_name => first_name ,
:last_name => last_name,
:avatar_url => photo_url,
:sex => sex,
:birthday => birthday,
:time_zone => time_zone,
:locale => locale,
:location => home_town
}
}
end
def process_callback
# The registration hash isolates the rest of the code from learning all the different structures
# of the omnia_hash
registration_hash = Users::OmniauthCallbacksController.build_registration_hash(#omniauth_hash)
logger.debug(registration_hash.to_yaml)
# Set the #user to nil
#user = nil
# Find if an authentication token for this provider and user id already exists
authentication = Authentication.find_by_provider_and_uid(#omniauth_hash['provider'], #omniauth_hash['uid'])
if authentication # We found an authentication
if user_signed_in? && (authentication.user.id != current_user.id)
flash[:error] = I18n.t "controllers.omniauth_callbacks.process_callback.error.account_already_taken",
:provider => registration_hash[:provider].capitalize,
:account => registration_hash[:email]
redirect_to edit_user_account_path(current_user)
return
end
else
# We could not find the authentication than create one
authentication = Authentication.new(:provider => #omniauth_hash['provider'], :uid => #omniauth_hash['uid'])
if user_signed_in?
authentication.user = current_user
else
registration_hash[:skip_confirmation] = true
authentication.user = User.find_by_email(registration_hash[:email]) || User.create_user(registration_hash)
end
end
#user = authentication.user
# save the authentication
authentication.token = #omniauth_hash
authentication.provider_name = registration_hash[:provider]
authentication.provider_username = registration_hash[:email]
if !authentication.save
logger.error(authentication.errors)
end
# If a user is signed in then he is trying to link a new account
if user_signed_in?
if authentication.persisted? # This was a linking operation so send back the user to the account edit page
flash[:success] = I18n.t "controllers.omniauth_callbacks.process_callback.success.link_account",
:provider => registration_hash[:provider].capitalize,
:account => registration_hash[:email]
else
flash[:error] = I18n.t "controllers.omniauth_callbacks.process_callback.error.link_account",
:provider => registration_hash[:provider].capitalize,
:account => registration_hash[:email],
:errors =>authentication.errors
end
redirect_to edit_user_account_path(current_user)
else
# This was a sign in operation so sign in the user and redirect it to his home page
if #user.persisted? && authentication.persisted?
flash[:success] = I18n.t "controllers.omniauth_callbacks.process_callback.success.sign_in",
:provider => registration_hash[:provider].capitalize,
:account => registration_hash[:email]
sign_in_and_redirect(:user,#user)
else
session['registration_hash'] = registration_hash
flash[:error] = I18n.t "controllers.omniauth_callbacks.process_callback.error.sign_in",
:provider => registration_hash[:provider].capitalize,
:account => registration_hash[:email]
redirect_to new_registration_users_url
end
end
end
def facebook
process_callback
end
def gmail
process_callback
end
Now you will notice that I call a User.create_user(registration_hash). This method implementation will depend on how your app create a user but at the minimum the method has to create a user and assign to it a random password:
def self.create_user(registration_hash)
logger.info "Creating new user with registration hash: #{registration_hash.to_yaml}"
unless registration_hash or resigration_hash.empty?
return nil
end
user = User.new
user.email = registration_hash[:email]
if registration_hash[:password]
user.password = registration_hash[:password]
else
user.password = Devise.friendly_token[0,20]
end
user.password_confirmation = user.password
# custom app code here...
if registration_hash[:skip_confirmation] == true
user.confirm!
end
user
end
Note: My app support login with other service so I have implemented a table that contain authentication tokens.
Hope this can get you started.
You can use this application do the all stuff
https://github.com/kashiftufail/facebook_login_using_devise_and_omniauth_facebook