us_zipcode 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis.yml +19 -0
  4. data/Gemfile +21 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.textile +179 -0
  7. data/README.textile~ +184 -0
  8. data/Rakefile +19 -0
  9. data/features/step_definitions/common_steps.rb +76 -0
  10. data/features/step_definitions/rails_setup_steps.rb +17 -0
  11. data/features/step_definitions/rails_setup_steps.rb~ +17 -0
  12. data/features/support/env.rb +10 -0
  13. data/features/support/string.rb +128 -0
  14. data/features/zipcodes.feature +24 -0
  15. data/features/zipcodes.feature~ +24 -0
  16. data/lib/generators/us_zipcode/models_generator.rb +41 -0
  17. data/lib/generators/us_zipcode/models_generator.rb~ +41 -0
  18. data/lib/generators/us_zipcode/templates/county_model.rb +17 -0
  19. data/lib/generators/us_zipcode/templates/county_model.rb~ +17 -0
  20. data/lib/generators/us_zipcode/templates/migration.rb +41 -0
  21. data/lib/generators/us_zipcode/templates/migration.rb~ +41 -0
  22. data/lib/generators/us_zipcode/templates/state_model.rb +15 -0
  23. data/lib/generators/us_zipcode/templates/state_model.rb~ +15 -0
  24. data/lib/generators/us_zipcode/templates/zipcode_model.rb +30 -0
  25. data/lib/generators/us_zipcode/templates/zipcode_model.rb~ +30 -0
  26. data/lib/generators/us_zipcode/templates/zipcodes.rake +163 -0
  27. data/lib/generators/us_zipcode/templates/zipcodes.rake~ +163 -0
  28. data/lib/generators/us_zipcode/version.rb +3 -0
  29. data/lib/generators/us_zipcode/version.rb~ +3 -0
  30. data/lib/my_zipcode_gem.rb~ +34 -0
  31. data/lib/us_zipcode.rb +29 -0
  32. data/lib/us_zipcode.rb~ +29 -0
  33. data/rails3_2.gemfile +21 -0
  34. data/rails4_0.gemfile +23 -0
  35. data/rails4_1.gemfile +23 -0
  36. data/us_zipcode.gemspec +24 -0
  37. data/us_zipcode.gemspec~ +24 -0
  38. metadata +108 -0
@@ -0,0 +1,128 @@
1
+ class String
2
+
3
+ class << self
4
+ def random(count = 6, ranges = [('a'..'z'),('A'..'Z'),('0'..'9')])
5
+ o = ranges.map{|i| i.to_a}.flatten;
6
+ string = (0..(count-1)).map{ o[rand(o.length)] }.join;
7
+ end
8
+ end
9
+
10
+ def left(count)
11
+ self.slice(0,count)
12
+ end
13
+
14
+ def right(count)
15
+ self.slice(-count,count)
16
+ end
17
+
18
+ def left_trim
19
+ # remove leading whitespace
20
+ self.gsub(/^[\t\s]+/, '')
21
+ end
22
+
23
+ def right_trim
24
+ # remove trailing whitespace
25
+ self.gsub(/[\t\s]+$/, '')
26
+ end
27
+
28
+ def trim
29
+ # remove leading and trailing whitespace
30
+ self.left_trim.right_trim
31
+ end
32
+
33
+ # html = <<-stop.here_with_pipe
34
+ # |<!-- Begin: comment -->
35
+ # |<script type="text/javascript">
36
+ # stop
37
+ def here_with_pipe(linefeeds = false)
38
+ lines = self.split("\n")
39
+ lines.map! {|c| c.sub!(/\s*\|/, '')}
40
+ new_string = lines.join(linefeeds ? "\n" : " ")
41
+ self.replace(new_string)
42
+ end
43
+
44
+ def is_alpha_numeric?
45
+ regex = /^[a-zA-Z0-9]+$/
46
+ return (self =~ regex) == 0 ? true : false
47
+ end
48
+
49
+ def is_email_address?
50
+ # //Email address
51
+ # //Use this version to seek out email addresses in random documents and texts.
52
+ # //Does not match email addresses using an IP address instead of a domain name.
53
+ # //Does not match email addresses on new-fangled top-level domains with more than 4 letters such as .museum.
54
+ # //Including these increases the risk of false positives when applying the regex to random documents.
55
+ # '\b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b'
56
+ #
57
+ # //Email address (anchored)
58
+ # //Use this anchored version to check if a valid email address was entered.
59
+ # //Does not match email addresses using an IP address instead of a domain name.
60
+ # //Does not match email addresses on new-fangled top-level domains with more than 4 letters such as .museum.
61
+ # //Requires the "case insensitive" option to be ON.
62
+ # '^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$'
63
+ #
64
+ # //Email address (anchored; no consecutive dots)
65
+ # //Use this anchored version to check if a valid email address was entered.
66
+ # //Improves on the original email address regex by excluding addresses with consecutive dots such as john@aol...com
67
+ # //Does not match email addresses using an IP address instead of a domain name.
68
+ # //Does not match email addresses on new-fangled top-level domains with more than 4 letters such as .museum.
69
+ # //Including these increases the risk of false positives when applying the regex to random documents.
70
+ # '^[A-Z0-9._%-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$'
71
+ #
72
+ # //Email address (no consecutive dots)
73
+ # //Use this version to seek out email addresses in random documents and texts.
74
+ # //Improves on the original email address regex by excluding addresses with consecutive dots such as john@aol...com
75
+ # //Does not match email addresses using an IP address instead of a domain name.
76
+ # //Does not match email addresses on new-fangled top-level domains with more than 4 letters such as .museum.
77
+ # //Including these increases the risk of false positives when applying the regex to random documents.
78
+ # '\b[A-Z0-9._%-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}\b'
79
+ #
80
+ # //Email address (specific TLDs)
81
+ # //Does not match email addresses using an IP address instead of a domain name.
82
+ # //Matches all country code top level domains, and specific common top level domains.
83
+ # '^[A-Z0-9._%-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|biz|info|name|aero|biz|info|jobs|museum|name)$'
84
+ #
85
+ # //Email address: Replace with HTML link
86
+ # '\b(?:mailto:)?([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})\b'
87
+
88
+ email_regex = %r{^[A-Z0-9._%-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|biz|info|name|aero|biz|info|jobs|museum|name)$}xi # Case insensitive
89
+
90
+ return (self =~ email_regex) == 0 ? true : false
91
+ end
92
+
93
+ def is_zipcode?
94
+ self =~ %r{^(\d{5})(-\d{4})?$}x ? true : false
95
+ end
96
+
97
+ def format_phone
98
+ '(' << slice(0..2) << ')' << slice(3..5) << '-' << slice(-4,4)
99
+ end
100
+
101
+ def is_numeric?
102
+ begin
103
+ Float(self)
104
+ rescue
105
+ false # not numeric
106
+ else
107
+ true # numeric
108
+ end
109
+ end
110
+
111
+ def sanitize
112
+ clean_string = self.gsub(/[^a-z0-9,! \-\(\)\:\;\.\&\$]+/i, '')
113
+ #p "SAN: #{clean_string}"
114
+ clean_string
115
+ end
116
+
117
+ def shorten(count = 30)
118
+ if self.length >= count
119
+ shortened = self[0, count]
120
+ splitted = shortened.split(/\s/)
121
+ words = splitted.length
122
+ splitted[0, words-1].join(" ") + ' ...'
123
+ else
124
+ self
125
+ end
126
+ end
127
+
128
+ end
@@ -0,0 +1,24 @@
1
+ Feature: Us ZipCode Gem
2
+ In order to manage zipcode resources
3
+ As a rails developer
4
+ I want to generate models for zipcode, county and state, and populate their tables
5
+
6
+ Scenario: Generate models and migration for zipcode, county and state
7
+ Given a new Rails app
8
+ Then I should see "us_zipcode:models" when running "rails g"
9
+ When I run "rails g us_zipcode:models"
10
+ Then I should see the following files
11
+ | app/models/zipcode.rb |
12
+ | app/models/state.rb |
13
+ | app/models/county.rb |
14
+ | lib/tasks/zipcodes.rake |
15
+ | db/migrate |
16
+ And I should see "gem "mocha"" in file "Gemfile"
17
+ And I should successfully run "rake db:migrate"
18
+
19
+ Scenario: Update data for zipcodes, counties and states tables
20
+ Given a new migrated Rails app
21
+ Then I should successfully run "rake zipcodes:update"
22
+ And I should see 51 records in the "states" table
23
+ And I should see 3142 records in the "counties" table
24
+ And I should see 42366 records in the "zipcodes" table
@@ -0,0 +1,24 @@
1
+ Feature: My Zipcode Gem
2
+ In order to manage zipcode resources
3
+ As a rails developer
4
+ I want to generate models for zipcode, county and state, and populate their tables
5
+
6
+ Scenario: Generate models and migration for zipcode, county and state
7
+ Given a new Rails app
8
+ Then I should see "my_zipcode_gem:models" when running "rails g"
9
+ When I run "rails g my_zipcode_gem:models"
10
+ Then I should see the following files
11
+ | app/models/zipcode.rb |
12
+ | app/models/state.rb |
13
+ | app/models/county.rb |
14
+ | lib/tasks/zipcodes.rake |
15
+ | db/migrate |
16
+ And I should see "gem "mocha"" in file "Gemfile"
17
+ And I should successfully run "rake db:migrate"
18
+
19
+ Scenario: Update data for zipcodes, counties and states tables
20
+ Given a new migrated Rails app
21
+ Then I should successfully run "rake zipcodes:update"
22
+ And I should see 51 records in the "states" table
23
+ And I should see 3142 records in the "counties" table
24
+ And I should see 42366 records in the "zipcodes" table
@@ -0,0 +1,41 @@
1
+ module UsZipcode
2
+ class ModelsGenerator < Base
3
+ include Rails::Generators::Migration
4
+
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ def initialize(*args, &block)
8
+ super
9
+ migration_template 'migration.rb', "db/migrate/create_us_zipcode_models.rb"
10
+ end
11
+
12
+ def generate_models
13
+ # puts ">>> generate_zipcodes:"
14
+ end
15
+
16
+ def add_gems
17
+ add_gem "mocha", :group => :test
18
+ end
19
+
20
+ def create_models
21
+ template 'zipcode_model.rb', "app/models/zipcode.rb"
22
+ template 'county_model.rb', "app/models/county.rb"
23
+ template 'state_model.rb', "app/models/state.rb"
24
+ end
25
+
26
+ # Implement the required interface for Rails::Generators::Migration.
27
+ # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
28
+ def self.next_migration_number(dirname)
29
+ if ActiveRecord::Base.timestamped_migrations
30
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
31
+ else
32
+ "%.3d" % (current_migration_number(dirname) + 1)
33
+ end
34
+ end
35
+
36
+ def create_rakefile
37
+ template 'zipcodes.rake', "lib/tasks/zipcodes.rake"
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ module MyZipcodeGem
2
+ class ModelsGenerator < Base
3
+ include Rails::Generators::Migration
4
+
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ def initialize(*args, &block)
8
+ super
9
+ migration_template 'migration.rb', "db/migrate/create_my_zipcode_gem_models.rb"
10
+ end
11
+
12
+ def generate_models
13
+ # puts ">>> generate_zipcodes:"
14
+ end
15
+
16
+ def add_gems
17
+ add_gem "mocha", :group => :test
18
+ end
19
+
20
+ def create_models
21
+ template 'zipcode_model.rb', "app/models/zipcode.rb"
22
+ template 'county_model.rb', "app/models/county.rb"
23
+ template 'state_model.rb', "app/models/state.rb"
24
+ end
25
+
26
+ # Implement the required interface for Rails::Generators::Migration.
27
+ # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
28
+ def self.next_migration_number(dirname)
29
+ if ActiveRecord::Base.timestamped_migrations
30
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
31
+ else
32
+ "%.3d" % (current_migration_number(dirname) + 1)
33
+ end
34
+ end
35
+
36
+ def create_rakefile
37
+ template 'zipcodes.rake', "lib/tasks/zipcodes.rake"
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ require 'memoist'
2
+ class County < ActiveRecord::Base
3
+ extend Memoist
4
+
5
+ belongs_to :state
6
+ has_many :zipcodes
7
+
8
+ validates :name, uniqueness: {:scope => :state_id, :case_sensitive => false}, presence: true
9
+
10
+ scope :without_zipcodes, -> { joins("LEFT JOIN zipcodes ON zipcodes.county_id = counties.id").where("zipcodes.county_id IS NULL")}
11
+ scope :without_state, -> {where("state_id IS NULL")}
12
+
13
+ def cities
14
+ zipcodes.map(&:city).sort.uniq
15
+ end
16
+ memoize :cities
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'memoist'
2
+ class County < ActiveRecord::Base
3
+ extend Memoist
4
+
5
+ belongs_to :state
6
+ has_many :zipcodes
7
+
8
+ validates :name, uniqueness: {:scope => :state_id, :case_sensitive => false}, :presence => true
9
+
10
+ scope :without_zipcodes, -> { joins("LEFT JOIN zipcodes ON zipcodes.county_id = counties.id").where("zipcodes.county_id IS NULL")}
11
+ scope :without_state, -> {where("state_id IS NULL")}
12
+
13
+ def cities
14
+ zipcodes.map(&:city).sort.uniq
15
+ end
16
+ memoize :cities
17
+ end
@@ -0,0 +1,41 @@
1
+ class CreateUsZipcodeModels < ActiveRecord::Migration
2
+ def self.up
3
+ # Zipcodes Table
4
+ create_table :zipcodes do |t|
5
+ t.string :code
6
+ t.string :city
7
+ t.integer :state_id, foreign_key: true
8
+ t.integer :county_id, foreign_key: true
9
+ t.decimal :lat, :precision => 15, :scale => 10
10
+ t.decimal :lon, :precision => 15, :scale => 10
11
+ t.timestamps
12
+ end
13
+ add_index :zipcodes, :code
14
+ add_index :zipcodes, :county_id
15
+ add_index :zipcodes, :state_id
16
+ add_index :zipcodes, [:lat, :lon]
17
+
18
+ # States Table
19
+ create_table :states do |t|
20
+ t.string :abbr, :limit => 2
21
+ t.string :name
22
+ t.timestamps
23
+ end
24
+ add_index :states, :abbr
25
+
26
+ # Counties Table
27
+ create_table :counties do |t|
28
+ t.integer :state_id
29
+ t.string :name
30
+ t.timestamps
31
+ end
32
+ add_index :counties, :name
33
+ add_index :counties, :state_id
34
+ end
35
+
36
+ def self.down
37
+ drop_table :counties
38
+ drop_table :states
39
+ drop_table :zipcodes
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ class CreateMyZipcodeGemModels < ActiveRecord::Migration
2
+ def self.up
3
+ # Zipcodes Table
4
+ create_table :zipcodes do |t|
5
+ t.string :code
6
+ t.string :city
7
+ t.integer :state_id, foreign_key: true
8
+ t.integer :county_id, foreign_key: true
9
+ t.decimal :lat, :precision => 15, :scale => 10
10
+ t.decimal :lon, :precision => 15, :scale => 10
11
+ t.timestamps
12
+ end
13
+ add_index :zipcodes, :code
14
+ add_index :zipcodes, :county_id
15
+ add_index :zipcodes, :state_id
16
+ add_index :zipcodes, [:lat, :lon]
17
+
18
+ # States Table
19
+ create_table :states do |t|
20
+ t.string :abbr, :limit => 2
21
+ t.string :name
22
+ t.timestamps
23
+ end
24
+ add_index :states, :abbr
25
+
26
+ # Counties Table
27
+ create_table :counties do |t|
28
+ t.integer :state_id
29
+ t.string :name
30
+ t.timestamps
31
+ end
32
+ add_index :counties, :name
33
+ add_index :counties, :state_id
34
+ end
35
+
36
+ def self.down
37
+ drop_table :counties
38
+ drop_table :states
39
+ drop_table :zipcodes
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ require 'memoist'
2
+ class State < ActiveRecord::Base
3
+ extend Memoist
4
+
5
+ has_many :zipcodes
6
+ has_many :counties
7
+
8
+ validates :abbr, uniqueness: { :case_sensitive => false }, presence: true
9
+ validates :name, uniqueness: { :case_sensitive => false }, presence: true
10
+
11
+ def cities
12
+ zipcodes.map(&:city).sort.uniq
13
+ end
14
+ memoize :cities
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'memoist'
2
+ class State < ActiveRecord::Base
3
+ extend Memoist
4
+
5
+ has_many :zipcodes
6
+ has_many :counties
7
+
8
+ validates :abbr, uniqueness: { :case_sensitive => false }, :presence => true
9
+ validates :name, uniqueness: { :case_sensitive => false }, :presence => true
10
+
11
+ def cities
12
+ zipcodes.map(&:city).sort.uniq
13
+ end
14
+ memoize :cities
15
+ end
@@ -0,0 +1,30 @@
1
+ class Zipcode < ActiveRecord::Base
2
+
3
+ belongs_to :county
4
+ belongs_to :state
5
+
6
+ validates :code, uniqueness: true, presence: true
7
+ validates :state_id, :county_id, :city, presence: true
8
+
9
+ scope :without_county, -> { where("county_id IS NULL") }
10
+ scope :without_state, -> { where("state_id IS NULL") }
11
+ scope :ungeocoded, -> { where("lat IS NULL OR lon IS NULL") }
12
+
13
+ class << self
14
+ def find_by_city(city)
15
+ includes(:county).where("city like '#{city}%'")
16
+ end
17
+ end
18
+
19
+ def county_and_zip
20
+ "#{county.name}: #{code}"
21
+ end
22
+
23
+ def latlon
24
+ [lat, lon]
25
+ end
26
+
27
+ def is_geocoded?
28
+ (!lat.nil? && !lon.nil?)
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ class Zipcode < ActiveRecord::Base
2
+
3
+ belongs_to :county
4
+ belongs_to :state
5
+
6
+ validates :code, uniqueness: true, presence: true
7
+ validates :state_id, :county_id, :city, :presence => true
8
+
9
+ scope :without_county, -> { where("county_id IS NULL") }
10
+ scope :without_state, -> { where("state_id IS NULL") }
11
+ scope :ungeocoded, -> { where("lat IS NULL OR lon IS NULL") }
12
+
13
+ class << self
14
+ def find_by_city(city)
15
+ includes(:county).where("city like '#{city}%'")
16
+ end
17
+ end
18
+
19
+ def county_and_zip
20
+ "#{county.name}: #{code}"
21
+ end
22
+
23
+ def latlon
24
+ [lat, lon]
25
+ end
26
+
27
+ def is_geocoded?
28
+ (!lat.nil? && !lon.nil?)
29
+ end
30
+ end
@@ -0,0 +1,163 @@
1
+ require 'open-uri'
2
+ require 'csv'
3
+ namespace :zipcodes do
4
+
5
+ desc "Update states table"
6
+ task :update_states => :environment do
7
+ puts ">>> Begin update of states table..."
8
+ url = "https://github.com/midwire/free_zipcode_data/raw/master/all_us_states.csv"
9
+ data = open(url)
10
+ file = nil
11
+ if data.is_a? StringIO
12
+ file = Tempfile.new('all_us_states.csv')
13
+ file.write(data.read)
14
+ file.flush
15
+ file.close
16
+ else
17
+ file = data
18
+ end
19
+ CSV.foreach(file.path, :headers => true) do |row|
20
+ puts "Updating state: [#{row['name']}]"
21
+ state = State.where(abbr: row['abbr']).first_or_initialize
22
+ state.update_attribute(:name, row['name'])
23
+ end
24
+ data.close
25
+ puts ">>> End update of states table..."
26
+ end
27
+
28
+ desc "Update counties table"
29
+ task :update_counties => :update_states do
30
+ puts ">>> Begin update of counties table..."
31
+ url = "https://github.com/midwire/free_zipcode_data/raw/master/all_us_counties.csv"
32
+ data = open(url)
33
+ file = nil
34
+ if data.is_a? StringIO
35
+ file = Tempfile.new('all_us_counties.csv')
36
+ file.write(data.read)
37
+ file.flush
38
+ file.close
39
+ else
40
+ file = data
41
+ end
42
+ CSV.foreach(file.path, :headers => true) do |row|
43
+ puts "Updating county: [#{row['name']}]"
44
+ # lookup state
45
+ state = State.find_by_abbr!(row['state'])
46
+ county = County.where(name: row['name'], state_id: state.to_param).first_or_initialize
47
+ county.save
48
+ end
49
+ data.close
50
+ puts ">>> End update of counties table..."
51
+ end
52
+
53
+ desc "Update zipcodes table"
54
+ task :update_zipcodes => :update_counties do
55
+ puts ">>> Begin update of zipcodes table..."
56
+ url = "https://github.com/midwire/free_zipcode_data/raw/master/all_us_zipcodes.csv"
57
+ data = open(url)
58
+ file = nil
59
+ if data.is_a? StringIO
60
+ file = Tempfile.new('all_us_zipcodes.csv')
61
+ file.write(data.read)
62
+ file.flush
63
+ file.close
64
+ else
65
+ file = data
66
+ end
67
+ CSV.foreach(file.path, :headers => true) do |row|
68
+ puts "Updating zipcode: [#{row['code']}], '#{row['city']}, #{row['state']}, #{row['county']}"
69
+ # lookup state
70
+ state = State.find_by_abbr!(row['state'])
71
+ begin
72
+ county = County.find_by_name_and_state_id!(row['county'], state.to_param)
73
+ rescue Exception => e
74
+ puts ">>> e: [#{e}]"
75
+ puts ">>>> No county found for zipcode: [#{row['code']}], '#{row['city']}, #{row['state']}, #{row['county']}... SKIPPING..."
76
+ next
77
+ end
78
+ zipcode = Zipcode.where(code: row['code']).first_or_initialize
79
+ zipcode.update_attributes!(
80
+ :city => row['city'].titleize,
81
+ :state_id => state.to_param,
82
+ :county_id => county.to_param,
83
+ :lat => row['lat'],
84
+ :lon => row['lon']
85
+ )
86
+ end
87
+ data.close
88
+ puts ">>> End update of zipcodes table..."
89
+ end
90
+
91
+ desc "Populate or update the zipcodes related tables"
92
+ task :update => :environment do
93
+ Rake::Task['zipcodes:update_zipcodes'].invoke
94
+ end
95
+
96
+ desc "Export US States to a .csv file"
97
+ task :export_states => :environment do
98
+ @states = State.order("name ASC")
99
+ csv_string = CSV.generate do |csv|
100
+ csv << ["abbr", "name"]
101
+ @states.each do |state|
102
+ csv << [
103
+ state.abbr,
104
+ state.name
105
+ ]
106
+ end
107
+ end
108
+ filename = "all_us_states.csv"
109
+ open("#{Rails.root}/db/#{filename}", 'w') do |f|
110
+ f.write(csv_string)
111
+ end
112
+ end
113
+
114
+ desc "Export all US Counties to a .csv file"
115
+ task :export_counties => :environment do
116
+ @counties = County.order("name ASC")
117
+ csv_string = CSV.generate do |csv|
118
+ csv << ["name", "state", "county_seat"]
119
+ @counties.each do |county|
120
+ csv << [
121
+ county.name,
122
+ county.state.abbr,
123
+ county.county_seat
124
+ ]
125
+ end
126
+ end
127
+ filename = "all_us_counties.csv"
128
+ open("#{Rails.root}/db/#{filename}", 'w') do |f|
129
+ f.write(csv_string)
130
+ end
131
+ end
132
+
133
+ desc "Export the zipcodes with county and state data"
134
+ task :export_zipcodes => :environment do
135
+ @zipcodes = Zipcode.order("code ASC")
136
+ csv_string = CSV.generate do |csv|
137
+ csv << ["code", "city", "state", "county", "area_code", "lat", "lon"]
138
+ @zipcodes.each do |zip|
139
+ csv << [
140
+ zip.code,
141
+ zip.city,
142
+ zip.state.abbr,
143
+ zip.county.nil? ? '' : zip.county.name,
144
+ zip.area_code,
145
+ zip.lat,
146
+ zip.lon
147
+ ]
148
+ end
149
+ end
150
+ filename = "all_us_zipcodes.csv"
151
+ open("#{Rails.root}/db/#{filename}", 'w') do |f|
152
+ f.write(csv_string)
153
+ end
154
+ end
155
+
156
+ desc "Export zipcodes, states and counties tables"
157
+ task :export => :environment do
158
+ Rake::Task['zipcodes:export_states'].invoke
159
+ Rake::Task['zipcodes:export_counties'].invoke
160
+ Rake::Task['zipcodes:export_zipcodes'].invoke
161
+ end
162
+
163
+ end