66
77require_relative '../etl/free_zipcode_data_job'
88
9- require 'pry' if ENV . fetch ( 'APP_ENV' ) == 'development'
9+ require 'pry' if ENV . fetch ( 'APP_ENV' , '' ) == 'development'
1010
1111module FreeZipcodeData
12+ # rubocop:disable Metrics/ClassLength
1213 class Runner
1314 attr_accessor :logger , :options
1415
@@ -23,30 +24,38 @@ def initialize
2324
2425 def start
2526 start_time = Time . now
26- options = FreeZipcodeData ::Options . instance
27- options . initialize_hash ( collect_args )
27+ opt = FreeZipcodeData ::Options . instance
28+ opt . initialize_hash ( collect_args )
29+ @options = opt . hash
2830
29- logger . info ( ' Starting FreeZipcodeData...' . green )
31+ logger . info ( " Starting FreeZipcodeData v #{ VERSION } ..." . green )
3032
31- datasource = DataSource . new ( options . hash . country )
33+ datasource = DataSource . new ( options . country )
3234 datasource . download
3335
34- database = SqliteRam . new ( File . join ( options . hash . work_dir , 'free_zipcode_data.sqlite3' ) )
36+ db_file = File . join ( options . work_dir , 'free_zipcode_data.sqlite3' )
37+ database = SqliteRam . new ( db_file )
38+ configure_meta ( database . conn , datasource . datafile )
3539
3640 %i[ country state county zipcode ] . each { |t | initialize_table ( t , database ) }
3741
3842 extract_transform_load ( datasource , database )
3943
44+ logger . info ( "Saving database to disk '#{ db_file } '..." )
4045 database . save_to_disk
4146
42- elapsed = Time . now - start_time
43- logger . info ( "Finished in [#{ elapsed } ] seconds." . yellow )
47+ if options . generate_files
48+ logger . info ( 'Generating .csv files...' )
49+ database . dump_tables ( options . work_dir )
50+ end
51+
52+ elapsed = Time . at ( Time . now - start_time ) . utc . strftime ( '%H:%M:%S' )
53+ logger . info ( "Processed #{ datasource_line_count } zipcodes in [#{ elapsed } ]." . yellow )
4454 end
4555
4656 private
4757
4858 def initialize_table ( table_sym , database )
49- options = Options . instance . hash
5059 tablename = options [ "#{ table_sym } _tablename" . to_sym ]
5160 logger . verbose ( "Initializing #{ table_sym } table: '#{ tablename } '..." )
5261 klass = instance_eval ( "#{ titleize ( table_sym ) } Table" , __FILE__ , __LINE__ )
@@ -57,12 +66,37 @@ def initialize_table(table_sym, database)
5766 table . build
5867 end
5968
69+ def datasource_line_count ( filename )
70+ @datasource_line_count ||= begin
71+ count = File . foreach ( filename ) . inject ( 0 ) { |c , _line | c + 1 }
72+ logger . verbose ( "Processing #{ count } zipcodes in '#{ filename } '..." )
73+ count
74+ end
75+ end
76+
77+ def configure_meta ( database , datasource )
78+ schema = <<-SQL
79+ create table meta (
80+ id integer not null primary key,
81+ name varchar(255),
82+ value varchar(255)
83+ )
84+ SQL
85+ database . execute_batch ( schema )
86+
87+ sql = <<-SQL
88+ INSERT INTO meta (name, value)
89+ VALUES ('line_count', #{ datasource_line_count ( datasource ) } )
90+ SQL
91+ database . execute ( sql )
92+ end
93+
6094 def extract_transform_load ( datasource , database )
6195 job = ETL ::FreeZipcodeDataJob . setup (
6296 datasource . datafile ,
6397 database . conn ,
6498 logger ,
65- FreeZipcodeData :: Options . instance . hash
99+ options
66100 )
67101 Kiba . run ( job )
68102 end
@@ -71,15 +105,20 @@ def extract_transform_load(datasource, database)
71105 # rubocop:disable Metrics/MethodLength
72106 def collect_args
73107 Trollop . options do
108+ opt (
109+ :work_dir ,
110+ 'REQUIRED: Specify your work/build directory, where the SQLite and .csv files will be built' ,
111+ type : :string , required : true , short : '-w'
112+ )
74113 opt (
75114 :country ,
76115 'Specify the country code for processing, or all countries if not specified' ,
77- type : :string , required : false , short : '-g '
116+ type : :string , required : false , short : '-f '
78117 )
79118 opt (
80- :work_dir ,
81- 'Specify your work/build directory, where the SQLite and .csv files will be built ' ,
82- type : :string , required : true , short : '-w'
119+ :generate_files ,
120+ 'Generate CSV files: [counties.csv, states.csv, countries .csv, zipcodes.csv] ' ,
121+ type : :boolean , required : false , short : '-g' , default : false
83122 )
84123 opt (
85124 :country_tablename ,
@@ -129,4 +168,5 @@ def titleize(string)
129168 ret
130169 end
131170 end
171+ # rubocop:enable Metrics/ClassLength
132172end
0 commit comments