ssn_validator 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +4 -0
  2. data/History.txt +41 -0
  3. data/LICENSE +20 -0
  4. data/PostInstall.txt +29 -0
  5. data/README.rdoc +98 -0
  6. data/Rakefile +60 -0
  7. data/VERSION.yml +5 -0
  8. data/generators/death_master_file_migration/death_master_file_migration_generator.rb +12 -0
  9. data/generators/death_master_file_migration/templates/migration.rb +26 -0
  10. data/generators/ssn_validator_migration/ssn_validator_migration_generator.rb +12 -0
  11. data/generators/ssn_validator_migration/templates/migration.rb +18 -0
  12. data/lib/ssn_validator.rb +12 -0
  13. data/lib/ssn_validator/models/death_master_file.rb +5 -0
  14. data/lib/ssn_validator/models/death_master_file_loader.rb +235 -0
  15. data/lib/ssn_validator/models/ssn_high_group_code.rb +5 -0
  16. data/lib/ssn_validator/models/ssn_high_group_code_loader.rb +87 -0
  17. data/lib/ssn_validator/models/ssn_validator.rb +94 -0
  18. data/lib/ssn_validator/ntis.rb +9 -0
  19. data/lib/tasks/ssn_validator.rake +24 -0
  20. data/rdoc/classes/DeathMasterFile.html +111 -0
  21. data/rdoc/classes/DeathMasterFileLoader.html +298 -0
  22. data/rdoc/classes/SsnHighGroupCode.html +111 -0
  23. data/rdoc/classes/SsnHighGroupCodeLoader.html +202 -0
  24. data/rdoc/classes/SsnValidator.html +116 -0
  25. data/rdoc/classes/SsnValidator/Ntis.html +111 -0
  26. data/rdoc/classes/SsnValidator/Ssn.html +315 -0
  27. data/rdoc/created.rid +1 -0
  28. data/rdoc/files/LICENSE.html +129 -0
  29. data/rdoc/files/README_rdoc.html +262 -0
  30. data/rdoc/files/lib/ssn_validator/models/death_master_file_loader_rb.html +112 -0
  31. data/rdoc/files/lib/ssn_validator/models/death_master_file_rb.html +108 -0
  32. data/rdoc/files/lib/ssn_validator/models/ssn_high_group_code_loader_rb.html +108 -0
  33. data/rdoc/files/lib/ssn_validator/models/ssn_high_group_code_rb.html +108 -0
  34. data/rdoc/files/lib/ssn_validator/models/ssn_validator_rb.html +101 -0
  35. data/rdoc/files/lib/ssn_validator/ntis_rb.html +101 -0
  36. data/rdoc/files/lib/ssn_validator_rb.html +113 -0
  37. data/rdoc/fr_class_index.html +33 -0
  38. data/rdoc/fr_file_index.html +35 -0
  39. data/rdoc/fr_method_index.html +37 -0
  40. data/rdoc/index.html +24 -0
  41. data/rdoc/rdoc-style.css +208 -0
  42. data/script/console +10 -0
  43. data/script/destroy +14 -0
  44. data/script/generate +14 -0
  45. data/ssn_validator.gemspec +130 -0
  46. data/test/files/test_dmf_funky_data_load.txt +6 -0
  47. data/test/files/test_dmf_initial_load.txt +5 -0
  48. data/test/files/test_dmf_update_load.txt +5 -0
  49. data/test/files/valid_csv_from_funky_data_file.txt +6 -0
  50. data/test/mocks/test/death_master_file_loader.rb +40 -0
  51. data/test/test_death_master_file_loader.rb +113 -0
  52. data/test/test_helper.rb +62 -0
  53. data/test/test_ssn_high_group_code_loader.rb +22 -0
  54. data/test/test_ssn_validator.rb +85 -0
  55. metadata +145 -0
@@ -0,0 +1,4 @@
1
+ *.DS_Store
2
+ *.svn
3
+ pkg
4
+ nbproject
@@ -0,0 +1,41 @@
1
+ == 1.0.4 2010-02-05
2
+
3
+ * 1 bug fixes:
4
+ * The ssa website changed it's process for the most recent month. Modified the rake task
5
+ to determine the most recent month loaded and bring it up to date.
6
+
7
+ == 1.0.3 2009-04-24
8
+
9
+ * 2 minor enhancement:
10
+ * Added method #death_master_file_record to SsnValidator::Ssn to return the actual dmf record if the SSN exists
11
+ * Changed the method #death_master_file_hit? to simply return true or false.
12
+
13
+ == 1.0.2 2009-04-24
14
+
15
+ * 1 minor enhancement:
16
+ * Using jeweler gem to create gemspec and rdoc files
17
+
18
+ == 1.0.1 2009-04-23
19
+
20
+ * 2 bug fixes:
21
+ * Fixed dmf mysql load error when single quote is in a data file record.
22
+ * Fixed ssn_validator:update_data rake task that broke on the last build.
23
+
24
+ == 1.0.0 2009-04-22
25
+
26
+ * 1 major enhancement:
27
+ * Added the death master file to determine if the ssn belongs to the deceased.
28
+
29
+ * 1 bug fix:
30
+ * Fixed bug where an error was thrown if the ssn area has not been assigned yet.
31
+
32
+ == 0.1.2 2009-04-15
33
+
34
+ * 2 minor enhancements:
35
+ * Added rdoc files
36
+ * Updated documentation
37
+
38
+ == 0.1.0 2009-04-14
39
+
40
+ * 1 major enhancement:
41
+ * Initial release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Kevin Tyll
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+
2
+ For more information on ssn_validator, see http://kevintyll.github.com/ssn_validator/
3
+
4
+ * To create the necessary db migration, from the command line, run:
5
+ script/generate ssn_validator_migration
6
+ * Require the gem in your environment.rb file in the Rails::Initializer block:
7
+ config.gem 'kevintyll-ssn_validator', :lib => 'ssn_validator'
8
+ * To load your table with the current SSN data, from the command line, run:
9
+ rake ssn_validator:update_data
10
+ * The SSN data is updated monthly, so you'll want to run this rake task monthly to keep your validations accurate.
11
+ * If you've purchased the death master file data, create the death_master_files migration:
12
+ script/generate death_master_file_migration
13
+ * To load the dmf files you receive from ntis:
14
+ rake ssn_validator:death_master_file:load_file PATH='path/to/file' AS_OF='2009-03-01'
15
+ * You'll need to pass in the full path to where the file is on disk. You'll also need
16
+ to pass in the date this file's data are as of in the format yyyy-mm-dd.
17
+ * This task must be used to load the initial file you receive from ntis on CD. It can optionally be used
18
+ to load the monthly update files you download from the website. If you manually download the update files,
19
+ you do not need to add your user name and password to the environment.rb file. For a more automated approach
20
+ to loading the update files, add your user name and password to the environment.rb file and use the 2nd rake task.
21
+ * To load the monthly updates from the ntis website:
22
+ * Add your user_name and password to the environment.rb file
23
+ SsnValidator::Ntis.user_name = 'REPLACE WITH YOUR dmf.ntis.gov USER NAME'
24
+ SsnValidator::Ntis.password = 'REPLACE WITH YOUR dmf.ntis.gov PASSWORD'
25
+ * Run the rake task:
26
+ rake ssn_validator:death_master_file:update_data
27
+ * This rake task will determine the most recent file that has been loaded, and loads all subsequent files in order
28
+ from the dmf.ntis.gov website.
29
+ * The death master file data is updated monthly, so you'll want to run this rake task monthly to keep your validations accurate.
@@ -0,0 +1,98 @@
1
+ = ssn_validator
2
+
3
+ * http://kevintyll.github.com/ssn_validator
4
+ * http://www.drexel-labs.com
5
+
6
+ == DESCRIPTION:
7
+
8
+ ssn_validator is a ruby gem that validates whether an SSN has likely been issued or not.
9
+ What exactly does that mean "likely" been issued? We can't tell for sure if an SSN belongs
10
+ to a particular person, but knowing the "rules"[http://www.socialsecurity.gov/employer/ssnweb.htm]
11
+ on how the social security administration assigns numbers, we can determine whether a number
12
+ has ever been issued or not.
13
+
14
+ ssn_validator started as a need for the company I work for, Clarity Services Inc. Incredibly, we
15
+ couldn't find an existing gem or service that provided what we needed. Since we were going to have
16
+ to roll our own solution, we decided to create a gem out of it and share it with the community. Much
17
+ thanks goes to the management at Clarity Services Inc. for allowing this code to be open sourced.
18
+
19
+
20
+ == FEATURES/PROBLEMS:
21
+
22
+ * What it can do:
23
+ Validates the likelyhood that an SSN has been issued to someone.
24
+ Checks the Death Master File if the SSN belongs to a dead person. This will require you to purchase the dmf data from https://dmf.ntis.gov
25
+
26
+ * What it cannot do:
27
+ Validate that an SSN actually belongs to a particular person.
28
+
29
+ * What it's planned to do:
30
+ Determine when an SSN was issued...if i can find the historical data. This can be used to further validate an SSN by comparing it to a Date of Birth.
31
+
32
+ == SYNOPSIS:
33
+
34
+ * Just instantiate the object with an SSN.
35
+ ssn = SsnValidator::Ssn.new('123-45-6789')
36
+
37
+ * Then check if it's valid
38
+ ssn.valid?
39
+ ssn.death_master_file_hit?
40
+
41
+ ssn.valid? only checks to see if the number itself is valid. Check the death_master_file_hit? method
42
+ as well to verify the ssn does not belong the the deceased.
43
+
44
+ The death_master_file_hit? method will only return true of false if you have purchased the dmf data and
45
+ loaded it into your database. There is a generator and rake task to facilitate this, but you'll have
46
+ to purchase the data yourself at https://dmf.ntis.gov.
47
+
48
+ * You can check the errors array to see why it's not valid.
49
+ ssn.errors
50
+
51
+ == REQUIREMENTS:
52
+
53
+ * Rails 2.0.0 or greater
54
+
55
+ == INSTALL:
56
+
57
+ * To install the gem:
58
+ sudo gem install kevintyll-ssn_validator
59
+ * To create the necessary db migration, from the command line, run:
60
+ script/generate ssn_validator_migration
61
+ * Require the gem in your environment.rb file in the Rails::Initializer block:
62
+ config.gem 'kevintyll-ssn_validator', :lib => 'ssn_validator'
63
+ * To load your table with the current SSN data, from the command line, run:
64
+ rake ssn_validator:update_data
65
+
66
+ * The SSN data is updated monthly, so you'll want to run this rake task monthly to keep your validations accurate.
67
+
68
+ * If you've purchased the death master file data, create the death_master_files migration:
69
+ script/generate death_master_file_migration
70
+ * To load the dmf files you receive from ntis:
71
+ rake ssn_validator:death_master_file:load_file PATH='path/to/file' AS_OF='2009-03-01'
72
+
73
+ * You'll need to pass in the full path to where the file is on disk. You'll also need
74
+ to pass in the date this file's data are as of in the format yyyy-mm-dd.
75
+
76
+ * This task must be used to load the initial file you receive from ntis on CD. It can optionally be used
77
+ to load the monthly update files you download from the website. If you manually download the update files,
78
+ you do not need to add your user name and password to the environment.rb file. For a more automated approach
79
+ to loading the update files, add your user name and password to the environment.rb file and use the 2nd rake task.
80
+
81
+ * To load the monthly updates from the ntis website:
82
+ * Add your user_name and password to the environment.rb file
83
+
84
+ SsnValidator::Ntis.user_name = 'REPLACE WITH YOUR dmf.ntis.gov USER NAME'
85
+ SsnValidator::Ntis.password = 'REPLACE WITH YOUR dmf.ntis.gov PASSWORD'
86
+
87
+ * Run the rake task:
88
+
89
+ rake ssn_validator:death_master_file:update_data
90
+
91
+ * This rake task will determine the most recent file that has been loaded, and loads all subsequent files in order
92
+ from the dmf.ntis.gov website.
93
+
94
+ * The death master file data is updated monthly, so you'll want to run this rake task monthly to keep your validations accurate.
95
+
96
+ == Copyright
97
+
98
+ Copyright (c) 2009 Kevin Tyll. See LICENSE for details.
@@ -0,0 +1,60 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "ssn_validator"
8
+ gemspec.author = "Kevin Tyll"
9
+ gemspec.email = "kevintyll@gmail.com"
10
+ gemspec.homepage = %q{http://kevintyll.git.com/ssn_validator}
11
+ gemspec.summary = "Validates whether an SSN has likely been issued or not."
12
+ gemspec.description = "Validates whether an SSN has likely been issued or not."
13
+ gemspec.post_install_message = File.readlines("PostInstall.txt").join("")
14
+ end
15
+
16
+ Jeweler::GemcutterTasks.new
17
+
18
+ rescue LoadError
19
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'test'
25
+ test.pattern = 'test/test_*.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/*_test.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ if File.exist?('VERSION.yml')
48
+ config = YAML.load(File.read('VERSION.yml'))
49
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
50
+ else
51
+ version = ""
52
+ end
53
+
54
+ rdoc.rdoc_dir = 'rdoc'
55
+ rdoc.title = "ssn_validator #{version}"
56
+ rdoc.rdoc_files.include('README*')
57
+ rdoc.rdoc_files.include('LICENSE*')
58
+ rdoc.rdoc_files.include('lib/**/*.rb')
59
+ end
60
+
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 1
3
+ :minor: 0
4
+ :patch: 4
5
+ :build:
@@ -0,0 +1,12 @@
1
+ class DeathMasterFileMigrationGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ #m.directory File.join('db')
5
+ m.migration_template 'migration.rb', 'db/migrate'
6
+ end
7
+ end
8
+
9
+ def file_name
10
+ "create_death_master_file_table"
11
+ end
12
+ end
@@ -0,0 +1,26 @@
1
+ class CreateDeathMasterFileTable < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :death_master_files do |t|
5
+ t.string :social_security_number
6
+ t.string :last_name
7
+ t.string :name_suffix
8
+ t.string :first_name
9
+ t.string :middle_name
10
+ t.string :verify_proof_code
11
+ t.date :date_of_death
12
+ t.date :date_of_birth
13
+ t.string :state_of_residence
14
+ t.string :last_known_zip_residence
15
+ t.string :last_known_zip_payment
16
+ t.time_stamps
17
+ t.date :as_of
18
+ end
19
+ add_index :death_master_files, :social_security_number, :unique => true
20
+ add_index :death_master_files, :as_of
21
+ end
22
+
23
+ def self.down
24
+ drop_table :death_master_files
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ class SsnValidatorMigrationGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ #m.directory File.join('db')
5
+ m.migration_template 'migration.rb', 'db/migrate'
6
+ end
7
+ end
8
+
9
+ def file_name
10
+ "create_ssn_validator_tables"
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ class CreateSsnValidatorTables < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :ssn_high_group_codes do |t|
5
+ t.date :as_of
6
+ t.string :area
7
+ t.string :group
8
+ t.timestamps
9
+ end
10
+
11
+ add_index :ssn_high_group_codes, [:area]
12
+ add_index :ssn_high_group_codes, [:area, :as_of]
13
+ end
14
+
15
+ def self.down
16
+ drop_table :ssn_high_group_codes
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'ssn_validator/models/ssn_high_group_code'
5
+ require 'ssn_validator/models/ssn_high_group_code_loader'
6
+ require 'ssn_validator/models/ssn_validator'
7
+ require 'ssn_validator/models/death_master_file'
8
+ require 'ssn_validator/models/death_master_file_loader'
9
+ require 'rake'
10
+
11
+ # Load rake file
12
+ import "#{File.dirname(__FILE__)}/tasks/ssn_validator.rake"
@@ -0,0 +1,5 @@
1
+ require 'activerecord'
2
+
3
+ class DeathMasterFile < ActiveRecord::Base
4
+
5
+ end
@@ -0,0 +1,235 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'activerecord'
4
+ require 'active_record/connection_adapters/mysql_adapter'
5
+ require 'ssn_validator/ntis'
6
+
7
+ class DeathMasterFileLoader
8
+
9
+ # path_or_url is the full path to the file to load on disk, or the url of an update file.
10
+ # as_of is a string in the formatt YYYY-MM-DD for which the file data is accurate.
11
+ def initialize(path_or_url,file_as_of)
12
+ @file_path_or_url = path_or_url
13
+ @file_as_of = file_as_of
14
+ valid?
15
+ end
16
+
17
+ def valid?
18
+ raise(ArgumentError, "path_or_url not specified") unless @file_path_or_url
19
+ raise(ArgumentError, "as_of not specified") unless @file_as_of
20
+ max_as_of = DeathMasterFile.maximum(:as_of)
21
+ raise(ArgumentError, "A more recent file has already been processed. DB as_of date #{max_as_of}") if max_as_of && (max_as_of >= @file_as_of.to_date)
22
+
23
+ if File.exists?(@file_path_or_url)
24
+ @download_file = File.open(@file_path_or_url)
25
+ elsif URI.parse(@file_path_or_url).kind_of?(URI::HTTP)
26
+ @download_file = get_file_from_web
27
+ else
28
+ raise(Errno::ENOENT, @file_path_or_url)
29
+ end
30
+ end
31
+
32
+ def load_file
33
+
34
+ if DeathMasterFile.connection.kind_of?(ActiveRecord::ConnectionAdapters::MysqlAdapter)
35
+ puts "Converting file to csv format for Mysql import. This could take several minutes."
36
+
37
+ csv_file = convert_file_to_csv
38
+
39
+ bulk_mysql_update(csv_file)
40
+ else
41
+ active_record_file_load
42
+ end
43
+
44
+ end
45
+
46
+ def get_file_from_web
47
+ uri = URI.parse(@file_path_or_url)
48
+
49
+ request = Net::HTTP::Get.new(uri.request_uri)
50
+ request.basic_auth(SsnValidator::Ntis.user_name,SsnValidator::Ntis.password)
51
+
52
+ http = Net::HTTP.new(uri.host, uri.port)
53
+ http.use_ssl = (uri.port == 443)
54
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
55
+
56
+ response = http.request(request)
57
+
58
+ raise(ArgumentError, "Invalid URL: #{@file_path_or_url}") if response.kind_of?(Net::HTTPNotFound)
59
+ raise(ArgumentError, "Authorization Required: Invalid username or password. Set the variables SsnValidator::Ntis.user_name and SsnValidator::Ntis.password in your environment.rb file.") if response.kind_of?(Net::HTTPUnauthorized)
60
+
61
+ return response.body
62
+ end
63
+
64
+ #Loads all the update files from dmf.ntis.gov.
65
+ #It starts with the last file loaded, and loads each
66
+ #missing file in sequence up to the current file.
67
+ def self.load_update_files_from_web
68
+ max_as_of = DeathMasterFile.maximum(:as_of)
69
+ run_file_date = max_as_of.beginning_of_month.next_month
70
+ last_file_date = Date.today.beginning_of_month
71
+ while run_file_date <= last_file_date
72
+ url = "https://dmf.ntis.gov/dmldata/monthly/MA#{run_file_date.strftime("%y%m%d")}"
73
+ puts "Loading file #{url}"
74
+ DeathMasterFileLoader.new(url,run_file_date.strftime("%Y-%m-%d")).load_file
75
+ run_file_date += 1.month
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ # Processes 28 million rows in 23 minutes. Input file 2.6GB output: 2.9GB.
82
+ # Used to convert a packed fixed-length file into csv for mysql import.
83
+ def convert_file_to_csv
84
+
85
+ csv_file = Tempfile.new("dmf") # create temp file for converted csv formmat.
86
+
87
+
88
+ start = Time.now
89
+ timenow = start.to_s(:db)
90
+
91
+ @delete_ssns = []
92
+
93
+ @download_file.each_with_index do |line,i|
94
+ action = record_action(line)
95
+ attributes_hash = text_to_hash(line)
96
+ if action == 'D'
97
+ #keep track of all the records to delete. We'll delete at the end all at once.
98
+ @delete_ssns << attributes_hash[:social_security_number]
99
+ else
100
+ # empty field for id to be generated by mysql.
101
+ newline = "``," +
102
+ # social_security_number
103
+ "`#{attributes_hash[:social_security_number]}`," +
104
+ # last_name
105
+ "`#{attributes_hash[:last_name]}`," +
106
+ # name_suffix
107
+ "`#{attributes_hash[:name_suffix]}`," +
108
+ # first_name
109
+ "`#{attributes_hash[:first_name]}`," +
110
+ # middle_name
111
+ "`#{attributes_hash[:middle_name]}`," +
112
+ # verify_proof_code
113
+ "`#{attributes_hash[:verify_proof_code]}`," +
114
+ # date_of_death - need YYYY-MM-DD.
115
+ "`#{attributes_hash[:date_of_death]}`," +
116
+ # date_of_birth - need YYYY-MM-DD.
117
+ "`#{attributes_hash[:date_of_birth]}`," +
118
+ # state_of_residence - must be code between 01 and 65 or else nil.
119
+ "`#{attributes_hash[:state_of_residence]}`," +
120
+ # last_known_zip_residence
121
+ "`#{attributes_hash[:last_known_zip_residence]}`," +
122
+ # last_known_zip_payment
123
+ "`#{attributes_hash[:last_known_zip_payment]}`," +
124
+ # created_at
125
+ "`#{timenow}`," +
126
+ # updated_at
127
+ "`#{timenow}`," +
128
+ # as_of
129
+ "`#{attributes_hash[:as_of]}`" +"\n"
130
+
131
+ csv_file.syswrite newline
132
+ puts "#{i} records processed." if (i % 25000 == 0) && (i > 0)
133
+ end
134
+ end
135
+ puts "File conversion ran for #{(Time.now - start) / 60} minutes."
136
+ return csv_file
137
+ end
138
+
139
+ #Uses active record to load the data.
140
+ #The benefit is it will work on any database.
141
+ #The downside is it's really slow.
142
+ def active_record_file_load
143
+ puts 'Importing file into database. This could take many minutes.'
144
+
145
+ @download_file.each_with_index do |line,i|
146
+ action = record_action(line)
147
+ attributes_hash = text_to_hash(line)
148
+ if action == 'D'
149
+ DeathMasterFile.destroy_all(['social_security_number = ?', attributes_hash[:social_security_number]])
150
+ else
151
+
152
+ # empty field for id to be generated by mysql.
153
+ # record_hash = {
154
+ # :as_of => @file_as_of.to_date.to_s(:db),
155
+ # :social_security_number => parse_record(line,:social_security_number),
156
+ # :last_name => parse_record(line,:last_name),
157
+ # :name_suffix => parse_record(line,:name_suffix),
158
+ # :first_name => parse_record(line,:first_name),
159
+ # :middle_name => parse_record(line,:middle_name),
160
+ # :verify_proof_code => parse_record(line,:verify_proof_code),
161
+ # :date_of_death => parse_record(line,:date_of_death),
162
+ # :date_of_birth => parse_record(line,:date_of_birth),
163
+ # # - must be code between 01 and 65 or else nil.
164
+ # :state_of_residence=> parse_record(line,:state_of_residence=),
165
+ # :last_known_zip_residence => parse_record(line,:last_known_zip_residence),
166
+ # :last_known_zip_payment => parse_record(line,:last_known_zip_payment)
167
+ # }
168
+
169
+ case action
170
+ when '',nil,' '
171
+ #the initial file leaves this field blank
172
+ DeathMasterFile.create(attributes_hash)
173
+ else
174
+ dmf = DeathMasterFile.find_by_social_security_number(attributes_hash[:social_security_number])
175
+ if dmf
176
+ #a record already exists, update this record
177
+ dmf.update_attributes(attributes_hash)
178
+ else
179
+ #create a new record
180
+ DeathMasterFile.create(attributes_hash)
181
+ end
182
+ end
183
+ end
184
+
185
+ puts "#{i} records processed." if (i % 2500 == 0) && (i > 0)
186
+
187
+ end
188
+
189
+ puts "Import complete."
190
+ end
191
+
192
+ # For mysql, use:
193
+ # LOAD DATA LOCAL INFILE 'ssdm1.csv' INTO TABLE death_master_files FIELDS TERMINATED BY ',' ENCLOSED BY "'" LINES TERMINATED BY '\n';
194
+ # This is a much faster way of loading large amounts of data into mysql. For information on the LOAD DATA command
195
+ # see http://dev.mysql.com/doc/refman/5.1/en/load-data.html
196
+ def bulk_mysql_update(csv_file)
197
+ puts "Importing into Mysql..."
198
+
199
+ #delete all the 'D' records
200
+ DeathMasterFile.delete_all(:social_security_number => @delete_ssns)
201
+
202
+ #This will insert new records, and replace records with existing ssns.
203
+ #This only works because there is a unique index on social_security_number.
204
+ mysql_command = <<-TEXT
205
+ LOAD DATA LOCAL INFILE '#{csv_file.path}' REPLACE INTO TABLE death_master_files FIELDS TERMINATED BY ',' ENCLOSED BY "`" LINES TERMINATED BY '\n';
206
+ TEXT
207
+
208
+ DeathMasterFile.connection.execute(mysql_command)
209
+ puts "Mysql import complete."
210
+
211
+ end
212
+
213
+ def record_action(line)
214
+ line[0,1].to_s.strip
215
+ end
216
+
217
+ def text_to_hash(line)
218
+
219
+ {:as_of => @file_as_of.to_date.to_s(:db),
220
+ :social_security_number => line[1,9].to_s.strip,
221
+ :last_name => line[10,20].to_s.strip,
222
+ :name_suffix => line[30,4].to_s.strip,
223
+ :first_name => line[34,15].to_s.strip,
224
+ :middle_name => line[49,15].to_s.strip,
225
+ :verify_proof_code => line[64,1].to_s.strip,
226
+ :date_of_death => (Date.strptime(line[65,8].to_s.strip,'%m%d%Y') rescue nil),
227
+ :date_of_birth => (Date.strptime(line[73,8].to_s.strip,'%m%d%Y') rescue nil),
228
+ # - must be code between 01 and 65 or else nil.
229
+ :state_of_residence => (line[81,2].to_s.strip.between?('01', '65') ? line[81,2].to_s.strip : nil),
230
+ :last_known_zip_residence => line[83,5].to_s.strip,
231
+ :last_known_zip_payment => line[88,5].to_s.strip}
232
+ rescue Exception => e
233
+ puts '@@@@@@@@@ Error = ' + e.message + ': ' + line.inspect
234
+ end
235
+ end