[image]
pjb3 (owner)

Forks

gist: 1348465 by johnmetta created November 08, 2011

Revisions

ee3b2a pjb3 June 26, 2009 51742c pjb3 June 26, 2009 160867 pjb3 June 26, 2009
gist: 136919 Download_button fork
public
public
Public Clone URL: git://gist.github.com/136919.git
Give this clone URL to anyone.
git clone git://gist.github.com/136919.git gist-136919
Embed All Files: show embed
load.rake #
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
user.rb #
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
zip.rb #
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.


You are viewing a mobilized version of this site...
View original page here

Mobilized by Mowser Mowser