ssn_validator 1.0.4

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 (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