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.
- data/.gitignore +4 -0
- data/History.txt +41 -0
- data/LICENSE +20 -0
- data/PostInstall.txt +29 -0
- data/README.rdoc +98 -0
- data/Rakefile +60 -0
- data/VERSION.yml +5 -0
- data/generators/death_master_file_migration/death_master_file_migration_generator.rb +12 -0
- data/generators/death_master_file_migration/templates/migration.rb +26 -0
- data/generators/ssn_validator_migration/ssn_validator_migration_generator.rb +12 -0
- data/generators/ssn_validator_migration/templates/migration.rb +18 -0
- data/lib/ssn_validator.rb +12 -0
- data/lib/ssn_validator/models/death_master_file.rb +5 -0
- data/lib/ssn_validator/models/death_master_file_loader.rb +235 -0
- data/lib/ssn_validator/models/ssn_high_group_code.rb +5 -0
- data/lib/ssn_validator/models/ssn_high_group_code_loader.rb +87 -0
- data/lib/ssn_validator/models/ssn_validator.rb +94 -0
- data/lib/ssn_validator/ntis.rb +9 -0
- data/lib/tasks/ssn_validator.rake +24 -0
- data/rdoc/classes/DeathMasterFile.html +111 -0
- data/rdoc/classes/DeathMasterFileLoader.html +298 -0
- data/rdoc/classes/SsnHighGroupCode.html +111 -0
- data/rdoc/classes/SsnHighGroupCodeLoader.html +202 -0
- data/rdoc/classes/SsnValidator.html +116 -0
- data/rdoc/classes/SsnValidator/Ntis.html +111 -0
- data/rdoc/classes/SsnValidator/Ssn.html +315 -0
- data/rdoc/created.rid +1 -0
- data/rdoc/files/LICENSE.html +129 -0
- data/rdoc/files/README_rdoc.html +262 -0
- data/rdoc/files/lib/ssn_validator/models/death_master_file_loader_rb.html +112 -0
- data/rdoc/files/lib/ssn_validator/models/death_master_file_rb.html +108 -0
- data/rdoc/files/lib/ssn_validator/models/ssn_high_group_code_loader_rb.html +108 -0
- data/rdoc/files/lib/ssn_validator/models/ssn_high_group_code_rb.html +108 -0
- data/rdoc/files/lib/ssn_validator/models/ssn_validator_rb.html +101 -0
- data/rdoc/files/lib/ssn_validator/ntis_rb.html +101 -0
- data/rdoc/files/lib/ssn_validator_rb.html +113 -0
- data/rdoc/fr_class_index.html +33 -0
- data/rdoc/fr_file_index.html +35 -0
- data/rdoc/fr_method_index.html +37 -0
- data/rdoc/index.html +24 -0
- data/rdoc/rdoc-style.css +208 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/ssn_validator.gemspec +130 -0
- data/test/files/test_dmf_funky_data_load.txt +6 -0
- data/test/files/test_dmf_initial_load.txt +5 -0
- data/test/files/test_dmf_update_load.txt +5 -0
- data/test/files/valid_csv_from_funky_data_file.txt +6 -0
- data/test/mocks/test/death_master_file_loader.rb +40 -0
- data/test/test_death_master_file_loader.rb +113 -0
- data/test/test_helper.rb +62 -0
- data/test/test_ssn_high_group_code_loader.rb +22 -0
- data/test/test_ssn_validator.rb +85 -0
- metadata +145 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
|
2
|
+
require 'net/http'
|
3
|
+
class SsnHighGroupCodeLoader
|
4
|
+
def self.load_all_high_group_codes_files
|
5
|
+
months = ['Jan','Feb','Mar','Apr','May','June','July','Aug','Sept','Oct','Nov','Dec']
|
6
|
+
run_file_date = SsnHighGroupCode.maximum(:as_of)
|
7
|
+
run_file_date = run_file_date ? run_file_date.next_month.beginning_of_month : Date.new(2003,11,01)
|
8
|
+
last_file_date = Date.today.beginning_of_month
|
9
|
+
while run_file_date <= last_file_date
|
10
|
+
file_processed = false
|
11
|
+
run_file_month = months[run_file_date.month - 1]
|
12
|
+
run_file_year = run_file_date.year
|
13
|
+
['','corrected'].each do |mod|
|
14
|
+
break if file_processed
|
15
|
+
['ssns','ssnvs'].each do |url_mod|
|
16
|
+
break if file_processed
|
17
|
+
(1..Date.today.day).each do |day|
|
18
|
+
string_day = day.to_s
|
19
|
+
string_day.insert(0,'0') if day < 10
|
20
|
+
string_year = run_file_year.to_s.last(2)
|
21
|
+
file_name = "HG#{run_file_month}#{string_day}#{string_year}#{mod}.txt"
|
22
|
+
text = Net::HTTP.get(URI.parse("http://www.socialsecurity.gov/employer/#{url_mod}/#{file_name}"))
|
23
|
+
unless text.include? 'File Not Found'
|
24
|
+
create_records(parse_text(text),extract_as_of_date(text))
|
25
|
+
run_file_date = run_file_date.next_month
|
26
|
+
file_processed = true
|
27
|
+
break
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
#Loads the most recent file from http://www.socialsecurity.gov/employer/ssns/highgroup.txt
|
36
|
+
def self.load_current_high_group_codes_file
|
37
|
+
text = Net::HTTP.get(URI.parse('http://www.socialsecurity.gov/employer/ssns/highgroup.txt'))
|
38
|
+
create_records(parse_text(text),extract_as_of_date(text))
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def self.already_loaded?(file_as_of_date)
|
45
|
+
SsnHighGroupCode.find_by_as_of(file_as_of_date)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.create_records(area_groups,file_as_of)
|
49
|
+
if already_loaded?(file_as_of)
|
50
|
+
puts "File as of #{file_as_of} has already been loaded."
|
51
|
+
else
|
52
|
+
area_groups.each do |area_group|
|
53
|
+
SsnHighGroupCode.create(area_group.merge!(:as_of => file_as_of.to_s(:db)))
|
54
|
+
end
|
55
|
+
puts "File as of #{file_as_of} loaded."
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#extract the date from the file in the format mm/dd/yy
|
60
|
+
def self.extract_as_of_date(text)
|
61
|
+
as_of_start_index = text =~ /\d\d\/\d\d\/\d\d/
|
62
|
+
Date.strptime($&,'%m/%d/%y') unless as_of_start_index.nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
#The formatting of the file is a little bit messy. Sometimes tabs are
|
66
|
+
#used as delimiters and sometimes spaces are used as delimiters. Also, the asterisks indicating recent changes are not
|
67
|
+
#necessary for our purposes
|
68
|
+
#Returns an array of hashes.
|
69
|
+
def self.parse_text(text)
|
70
|
+
text.gsub!('*',' ')
|
71
|
+
text.gsub!(/\t/, ' ')
|
72
|
+
text_array = text.split(/\n/).compact
|
73
|
+
area_groups = []
|
74
|
+
text_array.each do |t|
|
75
|
+
t.gsub!(/\s+/,' ')
|
76
|
+
next if t =~ /[[:alpha:]]/ #skip over the header lines
|
77
|
+
|
78
|
+
if t =~ /\d\d\d \d\d/ #we want the lines with area group pairs
|
79
|
+
t.gsub(/\d\d\d \d\d/) do |s|
|
80
|
+
area_group = s.split(' ')
|
81
|
+
area_groups << {:area => area_group.first, :group => area_group.last}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
return area_groups
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module SsnValidator
|
2
|
+
class Ssn
|
3
|
+
|
4
|
+
attr_reader :ssn,:area,:group,:serial_number,:as_of
|
5
|
+
attr_reader :errors
|
6
|
+
|
7
|
+
|
8
|
+
#Instantiate the object passing in a social security number.
|
9
|
+
#The ssn can be a string or integer, with or without the '-'s.
|
10
|
+
def initialize(ssn)
|
11
|
+
@errors = []
|
12
|
+
ssn = ssn.to_s
|
13
|
+
if ssn =~ /-/ && ssn !~ /\d\d\d-\d\d-\d\d\d\d/
|
14
|
+
@errors << 'Hyphen misplaced.'
|
15
|
+
end
|
16
|
+
|
17
|
+
ssn.gsub!('-','')
|
18
|
+
if ssn.to_s.size != 9
|
19
|
+
@errors << 'SSN not 9 digits long.'
|
20
|
+
end
|
21
|
+
|
22
|
+
if ssn =~ /\D/
|
23
|
+
@errors << 'Non-digit found.'
|
24
|
+
end
|
25
|
+
|
26
|
+
#known dummy numbers
|
27
|
+
if ["078051120","111111111","123456789","219099999","999999999"].include? ssn || (ssn >= "987654320" and ssn <= "987654329")
|
28
|
+
@errors << "Known dummy SSN."
|
29
|
+
end
|
30
|
+
#known invalid area, group and serial numbers
|
31
|
+
if ssn =~ /\d{3}00\d{4}|0000\Z/
|
32
|
+
@errors << "Invalid group or serial number."
|
33
|
+
end
|
34
|
+
|
35
|
+
@ssn = ssn
|
36
|
+
@area = ssn.first(3)
|
37
|
+
@group = ssn[3,2]
|
38
|
+
@serial_number = ssn.last(4)
|
39
|
+
|
40
|
+
if @errors.empty?
|
41
|
+
@ssn_high_group_code = SsnHighGroupCode.find_by_area(@area, :order => 'as_of desc')
|
42
|
+
if @ssn_high_group_code.nil?
|
43
|
+
@errors << "Area '#{@area}' has not been assigned."
|
44
|
+
else
|
45
|
+
@as_of = @ssn_high_group_code.as_of
|
46
|
+
|
47
|
+
define_group_ranks
|
48
|
+
|
49
|
+
if @group_ranks[@group] > @group_ranks[@ssn_high_group_code.group]
|
50
|
+
@errors << "Group '#{@group}' has not been assigned yet for area '#{@area}'"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
#Determines whether or not the passed in
|
59
|
+
#ssn passed all validations.
|
60
|
+
def valid?
|
61
|
+
@errors.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
#returns the death master record if there is one.
|
65
|
+
def death_master_file_record
|
66
|
+
DeathMasterFile.find_by_social_security_number(@ssn)
|
67
|
+
end
|
68
|
+
|
69
|
+
#Determines if the passed in ssn belongs to the deceased.
|
70
|
+
def death_master_file_hit?
|
71
|
+
!death_master_file_record.nil?
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def define_group_ranks
|
78
|
+
@group_ranks = {}
|
79
|
+
rank = 0
|
80
|
+
(1..9).step(2) do |group|
|
81
|
+
@group_ranks.merge!("0#{group.to_s}" => rank += 1)
|
82
|
+
end
|
83
|
+
(10..98).step(2) do |group|
|
84
|
+
@group_ranks.merge!(group.to_s => rank += 1)
|
85
|
+
end
|
86
|
+
(2..8).step(2) do |group|
|
87
|
+
@group_ranks.merge!("0#{group.to_s}" => rank += 1)
|
88
|
+
end
|
89
|
+
(11..99).step(2) do |group|
|
90
|
+
@group_ranks.merge!(group.to_s => rank += 1)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
namespace :ssn_validator do
|
3
|
+
desc "Loads the current file from http://www.socialsecurity.gov/employer/ssns/highgroup.txt if it hasn't already been loaded."
|
4
|
+
task :update_data => :environment do
|
5
|
+
SsnHighGroupCodeLoader.load_all_high_group_codes_files
|
6
|
+
end
|
7
|
+
|
8
|
+
namespace :death_master_file do
|
9
|
+
desc "Loads a death master file. Specify the path of the file: PATH=path. Specify the date of the data: AS_OF=YYYY-MM-DD. Optimized for Mysql databases."
|
10
|
+
task :load_file => :environment do
|
11
|
+
if ENV["PATH"] && ENV["AS_OF"]
|
12
|
+
DeathMasterFileLoader.new(ENV["PATH"],ENV["AS_OF"]).load_file
|
13
|
+
else
|
14
|
+
puts "You must specify the PATH and AS_OF variables: rake ssn_validator:death_master_file:load_file PATH='path/to/file' AS_OF='2009-03-01'"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Determines the most recent file that has been loaded, and loads all subsequent files in order from the dmf.ntis.gov website. Optimized for Mysql databases."
|
19
|
+
task :update_data => :environment do
|
20
|
+
DeathMasterFileLoader.load_update_files_from_web
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
+
<head>
|
8
|
+
<title>Class: DeathMasterFile</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
+
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
+
<script type="text/javascript">
|
13
|
+
// <![CDATA[
|
14
|
+
|
15
|
+
function popupCode( url ) {
|
16
|
+
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
+
}
|
18
|
+
|
19
|
+
function toggleCode( id ) {
|
20
|
+
if ( document.getElementById )
|
21
|
+
elem = document.getElementById( id );
|
22
|
+
else if ( document.all )
|
23
|
+
elem = eval( "document.all." + id );
|
24
|
+
else
|
25
|
+
return false;
|
26
|
+
|
27
|
+
elemStyle = elem.style;
|
28
|
+
|
29
|
+
if ( elemStyle.display != "block" ) {
|
30
|
+
elemStyle.display = "block"
|
31
|
+
} else {
|
32
|
+
elemStyle.display = "none"
|
33
|
+
}
|
34
|
+
|
35
|
+
return true;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Make codeblocks hidden by default
|
39
|
+
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
+
|
41
|
+
// ]]>
|
42
|
+
</script>
|
43
|
+
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
<div id="classHeader">
|
50
|
+
<table class="header-table">
|
51
|
+
<tr class="top-aligned-row">
|
52
|
+
<td><strong>Class</strong></td>
|
53
|
+
<td class="class-name-in-header">DeathMasterFile</td>
|
54
|
+
</tr>
|
55
|
+
<tr class="top-aligned-row">
|
56
|
+
<td><strong>In:</strong></td>
|
57
|
+
<td>
|
58
|
+
<a href="../files/lib/ssn_validator/models/death_master_file_rb.html">
|
59
|
+
lib/ssn_validator/models/death_master_file.rb
|
60
|
+
</a>
|
61
|
+
<br />
|
62
|
+
</td>
|
63
|
+
</tr>
|
64
|
+
|
65
|
+
<tr class="top-aligned-row">
|
66
|
+
<td><strong>Parent:</strong></td>
|
67
|
+
<td>
|
68
|
+
ActiveRecord::Base
|
69
|
+
</td>
|
70
|
+
</tr>
|
71
|
+
</table>
|
72
|
+
</div>
|
73
|
+
<!-- banner header -->
|
74
|
+
|
75
|
+
<div id="bodyContent">
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
<div id="contextContent">
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
</div>
|
84
|
+
|
85
|
+
|
86
|
+
</div>
|
87
|
+
|
88
|
+
|
89
|
+
<!-- if includes -->
|
90
|
+
|
91
|
+
<div id="section">
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
<!-- if method_list -->
|
101
|
+
|
102
|
+
|
103
|
+
</div>
|
104
|
+
|
105
|
+
|
106
|
+
<div id="validator-badges">
|
107
|
+
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
108
|
+
</div>
|
109
|
+
|
110
|
+
</body>
|
111
|
+
</html>
|
@@ -0,0 +1,298 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
+
<head>
|
8
|
+
<title>Class: DeathMasterFileLoader</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
+
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
+
<script type="text/javascript">
|
13
|
+
// <![CDATA[
|
14
|
+
|
15
|
+
function popupCode( url ) {
|
16
|
+
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
+
}
|
18
|
+
|
19
|
+
function toggleCode( id ) {
|
20
|
+
if ( document.getElementById )
|
21
|
+
elem = document.getElementById( id );
|
22
|
+
else if ( document.all )
|
23
|
+
elem = eval( "document.all." + id );
|
24
|
+
else
|
25
|
+
return false;
|
26
|
+
|
27
|
+
elemStyle = elem.style;
|
28
|
+
|
29
|
+
if ( elemStyle.display != "block" ) {
|
30
|
+
elemStyle.display = "block"
|
31
|
+
} else {
|
32
|
+
elemStyle.display = "none"
|
33
|
+
}
|
34
|
+
|
35
|
+
return true;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Make codeblocks hidden by default
|
39
|
+
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
+
|
41
|
+
// ]]>
|
42
|
+
</script>
|
43
|
+
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
<div id="classHeader">
|
50
|
+
<table class="header-table">
|
51
|
+
<tr class="top-aligned-row">
|
52
|
+
<td><strong>Class</strong></td>
|
53
|
+
<td class="class-name-in-header">DeathMasterFileLoader</td>
|
54
|
+
</tr>
|
55
|
+
<tr class="top-aligned-row">
|
56
|
+
<td><strong>In:</strong></td>
|
57
|
+
<td>
|
58
|
+
<a href="../files/lib/ssn_validator/models/death_master_file_loader_rb.html">
|
59
|
+
lib/ssn_validator/models/death_master_file_loader.rb
|
60
|
+
</a>
|
61
|
+
<br />
|
62
|
+
</td>
|
63
|
+
</tr>
|
64
|
+
|
65
|
+
<tr class="top-aligned-row">
|
66
|
+
<td><strong>Parent:</strong></td>
|
67
|
+
<td>
|
68
|
+
Object
|
69
|
+
</td>
|
70
|
+
</tr>
|
71
|
+
</table>
|
72
|
+
</div>
|
73
|
+
<!-- banner header -->
|
74
|
+
|
75
|
+
<div id="bodyContent">
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
<div id="contextContent">
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
</div>
|
84
|
+
|
85
|
+
<div id="method-list">
|
86
|
+
<h3 class="section-bar">Methods</h3>
|
87
|
+
|
88
|
+
<div class="name-list">
|
89
|
+
<a href="#M000006">get_file_from_web</a>
|
90
|
+
<a href="#M000005">load_file</a>
|
91
|
+
<a href="#M000007">load_update_files_from_web</a>
|
92
|
+
<a href="#M000003">new</a>
|
93
|
+
<a href="#M000004">valid?</a>
|
94
|
+
</div>
|
95
|
+
</div>
|
96
|
+
|
97
|
+
</div>
|
98
|
+
|
99
|
+
|
100
|
+
<!-- if includes -->
|
101
|
+
|
102
|
+
<div id="section">
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
<!-- if method_list -->
|
112
|
+
<div id="methods">
|
113
|
+
<h3 class="section-bar">Public Class methods</h3>
|
114
|
+
|
115
|
+
<div id="method-M000007" class="method-detail">
|
116
|
+
<a name="M000007"></a>
|
117
|
+
|
118
|
+
<div class="method-heading">
|
119
|
+
<a href="#M000007" class="method-signature">
|
120
|
+
<span class="method-name">load_update_files_from_web</span><span class="method-args">()</span>
|
121
|
+
</a>
|
122
|
+
</div>
|
123
|
+
|
124
|
+
<div class="method-description">
|
125
|
+
<p>
|
126
|
+
Loads all the update files from dmf.ntis.gov. It starts with the last file
|
127
|
+
loaded, and loads each missing file in sequence up to the current file.
|
128
|
+
</p>
|
129
|
+
<p><a class="source-toggle" href="#"
|
130
|
+
onclick="toggleCode('M000007-source');return false;">[Source]</a></p>
|
131
|
+
<div class="method-source-code" id="M000007-source">
|
132
|
+
<pre>
|
133
|
+
<span class="ruby-comment cmt"># File lib/ssn_validator/models/death_master_file_loader.rb, line 67</span>
|
134
|
+
<span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">load_update_files_from_web</span>
|
135
|
+
<span class="ruby-identifier">max_as_of</span> = <span class="ruby-constant">DeathMasterFile</span>.<span class="ruby-identifier">maximum</span>(<span class="ruby-identifier">:as_of</span>)
|
136
|
+
<span class="ruby-identifier">run_file_date</span> = <span class="ruby-identifier">max_as_of</span>.<span class="ruby-identifier">beginning_of_month</span>.<span class="ruby-identifier">next_month</span>
|
137
|
+
<span class="ruby-identifier">last_file_date</span> = <span class="ruby-constant">Date</span>.<span class="ruby-identifier">today</span>.<span class="ruby-identifier">beginning_of_month</span>
|
138
|
+
<span class="ruby-keyword kw">while</span> <span class="ruby-identifier">run_file_date</span> <span class="ruby-operator"><=</span> <span class="ruby-identifier">last_file_date</span>
|
139
|
+
<span class="ruby-identifier">url</span> = <span class="ruby-node">"https://dmf.ntis.gov/dmldata/monthly/MA#{run_file_date.strftime("%y%m%d")}"</span>
|
140
|
+
<span class="ruby-identifier">puts</span> <span class="ruby-node">"Loading file #{url}"</span>
|
141
|
+
<span class="ruby-constant">DeathMasterFileLoader</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">url</span>,<span class="ruby-identifier">run_file_date</span>.<span class="ruby-identifier">strftime</span>(<span class="ruby-value str">"%Y-%m-%d"</span>)).<span class="ruby-identifier">load_file</span>
|
142
|
+
<span class="ruby-identifier">run_file_date</span> <span class="ruby-operator">+=</span> <span class="ruby-value">1</span>.<span class="ruby-identifier">month</span>
|
143
|
+
<span class="ruby-keyword kw">end</span>
|
144
|
+
<span class="ruby-keyword kw">end</span>
|
145
|
+
</pre>
|
146
|
+
</div>
|
147
|
+
</div>
|
148
|
+
</div>
|
149
|
+
|
150
|
+
<div id="method-M000003" class="method-detail">
|
151
|
+
<a name="M000003"></a>
|
152
|
+
|
153
|
+
<div class="method-heading">
|
154
|
+
<a href="#M000003" class="method-signature">
|
155
|
+
<span class="method-name">new</span><span class="method-args">(path_or_url,file_as_of)</span>
|
156
|
+
</a>
|
157
|
+
</div>
|
158
|
+
|
159
|
+
<div class="method-description">
|
160
|
+
<p>
|
161
|
+
path_or_url is the full path to the file to load on disk, or the url of an
|
162
|
+
update file. as_of is a string in the formatt YYYY-MM-DD for which the file
|
163
|
+
data is accurate.
|
164
|
+
</p>
|
165
|
+
<p><a class="source-toggle" href="#"
|
166
|
+
onclick="toggleCode('M000003-source');return false;">[Source]</a></p>
|
167
|
+
<div class="method-source-code" id="M000003-source">
|
168
|
+
<pre>
|
169
|
+
<span class="ruby-comment cmt"># File lib/ssn_validator/models/death_master_file_loader.rb, line 11</span>
|
170
|
+
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">path_or_url</span>,<span class="ruby-identifier">file_as_of</span>)
|
171
|
+
<span class="ruby-ivar">@file_path_or_url</span> = <span class="ruby-identifier">path_or_url</span>
|
172
|
+
<span class="ruby-ivar">@file_as_of</span> = <span class="ruby-identifier">file_as_of</span>
|
173
|
+
<span class="ruby-identifier">valid?</span>
|
174
|
+
<span class="ruby-keyword kw">end</span>
|
175
|
+
</pre>
|
176
|
+
</div>
|
177
|
+
</div>
|
178
|
+
</div>
|
179
|
+
|
180
|
+
<h3 class="section-bar">Public Instance methods</h3>
|
181
|
+
|
182
|
+
<div id="method-M000006" class="method-detail">
|
183
|
+
<a name="M000006"></a>
|
184
|
+
|
185
|
+
<div class="method-heading">
|
186
|
+
<a href="#M000006" class="method-signature">
|
187
|
+
<span class="method-name">get_file_from_web</span><span class="method-args">()</span>
|
188
|
+
</a>
|
189
|
+
</div>
|
190
|
+
|
191
|
+
<div class="method-description">
|
192
|
+
<p><a class="source-toggle" href="#"
|
193
|
+
onclick="toggleCode('M000006-source');return false;">[Source]</a></p>
|
194
|
+
<div class="method-source-code" id="M000006-source">
|
195
|
+
<pre>
|
196
|
+
<span class="ruby-comment cmt"># File lib/ssn_validator/models/death_master_file_loader.rb, line 46</span>
|
197
|
+
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">get_file_from_web</span>
|
198
|
+
<span class="ruby-identifier">uri</span> = <span class="ruby-constant">URI</span>.<span class="ruby-identifier">parse</span>(<span class="ruby-ivar">@file_path_or_url</span>)
|
199
|
+
|
200
|
+
<span class="ruby-identifier">request</span> = <span class="ruby-constant">Net</span><span class="ruby-operator">::</span><span class="ruby-constant">HTTP</span><span class="ruby-operator">::</span><span class="ruby-constant">Get</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">uri</span>.<span class="ruby-identifier">request_uri</span>)
|
201
|
+
<span class="ruby-identifier">request</span>.<span class="ruby-identifier">basic_auth</span>(<span class="ruby-constant">SsnValidator</span><span class="ruby-operator">::</span><span class="ruby-constant">Ntis</span>.<span class="ruby-identifier">user_name</span>,<span class="ruby-constant">SsnValidator</span><span class="ruby-operator">::</span><span class="ruby-constant">Ntis</span>.<span class="ruby-identifier">password</span>)
|
202
|
+
|
203
|
+
<span class="ruby-identifier">http</span> = <span class="ruby-constant">Net</span><span class="ruby-operator">::</span><span class="ruby-constant">HTTP</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">uri</span>.<span class="ruby-identifier">host</span>, <span class="ruby-identifier">uri</span>.<span class="ruby-identifier">port</span>)
|
204
|
+
<span class="ruby-identifier">http</span>.<span class="ruby-identifier">use_ssl</span> = (<span class="ruby-identifier">uri</span>.<span class="ruby-identifier">port</span> <span class="ruby-operator">==</span> <span class="ruby-value">443</span>)
|
205
|
+
<span class="ruby-identifier">http</span>.<span class="ruby-identifier">verify_mode</span> = <span class="ruby-constant">OpenSSL</span><span class="ruby-operator">::</span><span class="ruby-constant">SSL</span><span class="ruby-operator">::</span><span class="ruby-constant">VERIFY_NONE</span>
|
206
|
+
|
207
|
+
<span class="ruby-identifier">response</span> = <span class="ruby-identifier">http</span>.<span class="ruby-identifier">request</span>(<span class="ruby-identifier">request</span>)
|
208
|
+
|
209
|
+
<span class="ruby-identifier">raise</span>(<span class="ruby-constant">ArgumentError</span>, <span class="ruby-node">"Invalid URL: #{@file_path_or_url}"</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">response</span>.<span class="ruby-identifier">kind_of?</span>(<span class="ruby-constant">Net</span><span class="ruby-operator">::</span><span class="ruby-constant">HTTPNotFound</span>)
|
210
|
+
<span class="ruby-identifier">raise</span>(<span class="ruby-constant">ArgumentError</span>, <span class="ruby-value str">"Authorization Required: Invalid username or password. Set the variables SsnValidator::Ntis.user_name and SsnValidator::Ntis.password in your environment.rb file."</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">response</span>.<span class="ruby-identifier">kind_of?</span>(<span class="ruby-constant">Net</span><span class="ruby-operator">::</span><span class="ruby-constant">HTTPUnauthorized</span>)
|
211
|
+
|
212
|
+
<span class="ruby-keyword kw">return</span> <span class="ruby-identifier">response</span>.<span class="ruby-identifier">body</span>
|
213
|
+
<span class="ruby-keyword kw">end</span>
|
214
|
+
</pre>
|
215
|
+
</div>
|
216
|
+
</div>
|
217
|
+
</div>
|
218
|
+
|
219
|
+
<div id="method-M000005" class="method-detail">
|
220
|
+
<a name="M000005"></a>
|
221
|
+
|
222
|
+
<div class="method-heading">
|
223
|
+
<a href="#M000005" class="method-signature">
|
224
|
+
<span class="method-name">load_file</span><span class="method-args">()</span>
|
225
|
+
</a>
|
226
|
+
</div>
|
227
|
+
|
228
|
+
<div class="method-description">
|
229
|
+
<p><a class="source-toggle" href="#"
|
230
|
+
onclick="toggleCode('M000005-source');return false;">[Source]</a></p>
|
231
|
+
<div class="method-source-code" id="M000005-source">
|
232
|
+
<pre>
|
233
|
+
<span class="ruby-comment cmt"># File lib/ssn_validator/models/death_master_file_loader.rb, line 32</span>
|
234
|
+
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">load_file</span>
|
235
|
+
|
236
|
+
<span class="ruby-keyword kw">if</span> <span class="ruby-constant">DeathMasterFile</span>.<span class="ruby-identifier">connection</span>.<span class="ruby-identifier">kind_of?</span>(<span class="ruby-constant">ActiveRecord</span><span class="ruby-operator">::</span><span class="ruby-constant">ConnectionAdapters</span><span class="ruby-operator">::</span><span class="ruby-constant">MysqlAdapter</span>)
|
237
|
+
<span class="ruby-identifier">puts</span> <span class="ruby-value str">"Converting file to csv format for Mysql import. This could take several minutes."</span>
|
238
|
+
|
239
|
+
<span class="ruby-identifier">csv_file</span> = <span class="ruby-identifier">convert_file_to_csv</span>
|
240
|
+
|
241
|
+
<span class="ruby-identifier">bulk_mysql_update</span>(<span class="ruby-identifier">csv_file</span>)
|
242
|
+
<span class="ruby-keyword kw">else</span>
|
243
|
+
<span class="ruby-identifier">active_record_file_load</span>
|
244
|
+
<span class="ruby-keyword kw">end</span>
|
245
|
+
|
246
|
+
<span class="ruby-keyword kw">end</span>
|
247
|
+
</pre>
|
248
|
+
</div>
|
249
|
+
</div>
|
250
|
+
</div>
|
251
|
+
|
252
|
+
<div id="method-M000004" class="method-detail">
|
253
|
+
<a name="M000004"></a>
|
254
|
+
|
255
|
+
<div class="method-heading">
|
256
|
+
<a href="#M000004" class="method-signature">
|
257
|
+
<span class="method-name">valid?</span><span class="method-args">()</span>
|
258
|
+
</a>
|
259
|
+
</div>
|
260
|
+
|
261
|
+
<div class="method-description">
|
262
|
+
<p><a class="source-toggle" href="#"
|
263
|
+
onclick="toggleCode('M000004-source');return false;">[Source]</a></p>
|
264
|
+
<div class="method-source-code" id="M000004-source">
|
265
|
+
<pre>
|
266
|
+
<span class="ruby-comment cmt"># File lib/ssn_validator/models/death_master_file_loader.rb, line 17</span>
|
267
|
+
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">valid?</span>
|
268
|
+
<span class="ruby-identifier">raise</span>(<span class="ruby-constant">ArgumentError</span>, <span class="ruby-value str">"path_or_url not specified"</span>) <span class="ruby-keyword kw">unless</span> <span class="ruby-ivar">@file_path_or_url</span>
|
269
|
+
<span class="ruby-identifier">raise</span>(<span class="ruby-constant">ArgumentError</span>, <span class="ruby-value str">"as_of not specified"</span>) <span class="ruby-keyword kw">unless</span> <span class="ruby-ivar">@file_as_of</span>
|
270
|
+
<span class="ruby-identifier">max_as_of</span> = <span class="ruby-constant">DeathMasterFile</span>.<span class="ruby-identifier">maximum</span>(<span class="ruby-identifier">:as_of</span>)
|
271
|
+
<span class="ruby-identifier">raise</span>(<span class="ruby-constant">ArgumentError</span>, <span class="ruby-node">"A more recent file has already been processed. DB as_of date #{max_as_of}"</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">max_as_of</span> <span class="ruby-operator">&&</span> (<span class="ruby-identifier">max_as_of</span> <span class="ruby-operator">>=</span> <span class="ruby-ivar">@file_as_of</span>.<span class="ruby-identifier">to_date</span>)
|
272
|
+
|
273
|
+
<span class="ruby-keyword kw">if</span> <span class="ruby-constant">File</span>.<span class="ruby-identifier">exists?</span>(<span class="ruby-ivar">@file_path_or_url</span>)
|
274
|
+
<span class="ruby-ivar">@download_file</span> = <span class="ruby-constant">File</span>.<span class="ruby-identifier">open</span>(<span class="ruby-ivar">@file_path_or_url</span>)
|
275
|
+
<span class="ruby-keyword kw">elsif</span> <span class="ruby-constant">URI</span>.<span class="ruby-identifier">parse</span>(<span class="ruby-ivar">@file_path_or_url</span>).<span class="ruby-identifier">kind_of?</span>(<span class="ruby-constant">URI</span><span class="ruby-operator">::</span><span class="ruby-constant">HTTP</span>)
|
276
|
+
<span class="ruby-ivar">@download_file</span> = <span class="ruby-identifier">get_file_from_web</span>
|
277
|
+
<span class="ruby-keyword kw">else</span>
|
278
|
+
<span class="ruby-identifier">raise</span>(<span class="ruby-constant">Errno</span><span class="ruby-operator">::</span><span class="ruby-constant">ENOENT</span>, <span class="ruby-ivar">@file_path_or_url</span>)
|
279
|
+
<span class="ruby-keyword kw">end</span>
|
280
|
+
<span class="ruby-keyword kw">end</span>
|
281
|
+
</pre>
|
282
|
+
</div>
|
283
|
+
</div>
|
284
|
+
</div>
|
285
|
+
|
286
|
+
|
287
|
+
</div>
|
288
|
+
|
289
|
+
|
290
|
+
</div>
|
291
|
+
|
292
|
+
|
293
|
+
<div id="validator-badges">
|
294
|
+
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
295
|
+
</div>
|
296
|
+
|
297
|
+
</body>
|
298
|
+
</html>
|