pjb3 (owner)
Forks
gist: 1348465 by johnmetta created November 08, 2011
Private Gist
All pages are served over SSL and all pushing and pulling is done over SSH. No one may fork, clone, or view it unless they are given this private URL.
Every gist with this icon (
) is private.
Public Gist
Anyone may fork, clone, or view it.
Every repository with this icon (
) is public.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
namespace :load do
ZIP_CODE_DATA_URL = 'http://www.census.gov/tiger/tms/gazetteer/zips.txt'
# Swiped from ActiveRecord migrations.rb
def announce(message)
length = [0, 75 - message.length].max
puts "== %s %s" % [message, "=" * length]
end
desc "Loads zip codes from #{ZIP_CODE_DATA_URL}"
task :zip_codes => :environment do
begin
time = Benchmark.measure do
require 'fastercsv'
require 'open-uri'
FasterCSV.parse(open(ZIP_CODE_DATA_URL).read) do |row|
# Connascence of Position, Jim Weirich forgive me!
zip = Zip.create!(
:code => row[1],
:state => row[2],
:city => row[3],
:lat => row[4],
:lon => row[5])
puts "%20s, %2s, %5s" % [zip.city, zip.state, zip.code]
end
end
announce "Loaded %5d zip codes in (%2dm %2.0fs)" % [Zip.count, *time.real.divmod(60)]
rescue LoadError
puts "This rake task requires fastercsv. To install, run this command:\n\n sudo gem install fastercsv\n\n"
end
end
desc "Creates n number random users using the Random Data gem, defaults to 1000"
task :random_users, :n, :needs => :environment do |t, args|
begin
n = args.n.to_i < 1 ? 1000 : args.n.to_i
time = Benchmark.measure do
require 'random_data'
domains = %w[yahoo.com gmail.com privacy.net webmail.com msn.com hotmail.com example.com privacy.net]
zips = Zip.all #Can we fit 29k zip codes into memory?
n.times do |i|
user = User.new(:first_name => Random.firstname, :last_name => Random.lastname)
user.username = "#{user.first_name[0,1]}#{user.last_name}#{i}".downcase
user.password = user.password_confirmation = "secret"
user.email = "#{user.username}\@#{domains.rand}"
user.address = Random.address_line_1
zip = zips.rand
user.city = zip.city.titleize
user.state = zip.state
user.zip = zip
user.save!
puts "%6d: %15s %15s, %30s, %20s, %2s, %5s" % [(i+1), user.first_name, user.last_name, user.email, user.city, user.state, user.zip.code]
end
end
announce "Loaded %6d users in (%2dm %2.0fs)" % [n, *time.real.divmod(60)]
rescue LoadError
puts "This rake task requires random_data. To install, run this command:\n\n sudo gem install random_data\n\n"
end
end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class User < ActiveRecord::Base
belongs_to :zip
named_scope :within_miles_of_zip, lambda{|radius, zip|
# Get the parameters for the search
area = zip.area_for(radius)
# now find all zip codes that are within
# these min/max lat/lon bounds and return them
# weed out any zip codes that fall outside of the search radius
{ :select => "#{User.columns.map{|c| "users.#{c.name}"}.join(', ')}, sqrt(
pow(#{area[:lat_miles]} * (zips.lat - #{zip.lat}),2) +
pow(#{area[:lon_miles]} * (zips.lon - #{zip.lon}),2)) as distance",
:joins => :zip,
:conditions => "(zips.lat BETWEEN #{area[:min_lat]} AND #{area[:max_lat]})
AND (zips.lon BETWEEN #{area[:min_lon]} AND #{area[:max_lon]})
AND sqrt(pow(#{area[:lat_miles]} * (zips.lat - #{zip.lat}),2) +
pow(#{area[:lon_miles]} * (zips.lon - #{zip.lon}),2)) <= #{area[:radius]}",
:order => "distance"}
}
def within_miles(radius)
self.class.within_miles_of_zip(radius, zip)
end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Zip < ActiveRecord::Base
has_many :users
def self.code(code)
first(:conditions => {:code => code})
end
# Returns a hash with values that can be used
# to perform a proximity search query
def area_for(radius)
area = {}
area[:radius] = radius.to_f
area[:lat_miles] = 69.172 #this is constant
#longitude miles varies based on latitude, that is calculated here
area[:lon_miles] = (area[:lat_miles] * Math.cos(lat * (Math::PI/180))).abs
area[:lat_degrees] = radius/area[:lat_miles] #radius in degrees latitude
area[:lon_degrees] = radius/area[:lon_miles] #radius in degrees longitude
#now set min and max lat and long accordingly
area[:min_lat] = lat - area[:lat_degrees]
area[:max_lat] = lat + area[:lat_degrees]
area[:min_lon] = lon - area[:lon_degrees]
area[:max_lon] = lon + area[:lon_degrees]
area
end
end
Please log in to comment.






