ssn_validator 1.0.9 → 1.0.10
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/History.txt +5 -0
- data/Rakefile +61 -60
- data/VERSION.yml +1 -1
- data/lib/ssn_validator/models/death_master_file_loader.rb +46 -43
- data/rdoc/DeathMasterFile.html +139 -0
- data/rdoc/DeathMasterFileLoader.html +384 -0
- data/rdoc/LICENSE.html +116 -0
- data/rdoc/README_rdoc.html +226 -0
- data/rdoc/SsnHighGroupCode.html +139 -0
- data/rdoc/SsnHighGroupCodeLoader.html +251 -0
- data/rdoc/SsnValidator/Ntis.html +139 -0
- data/rdoc/SsnValidator/Ssn.html +417 -0
- data/rdoc/SsnValidator.html +134 -0
- data/rdoc/created.rid +10 -1
- data/rdoc/images/add.png +0 -0
- data/rdoc/images/brick.png +0 -0
- data/rdoc/images/brick_link.png +0 -0
- data/rdoc/images/bug.png +0 -0
- data/rdoc/images/bullet_black.png +0 -0
- data/rdoc/images/bullet_toggle_minus.png +0 -0
- data/rdoc/images/bullet_toggle_plus.png +0 -0
- data/rdoc/images/date.png +0 -0
- data/rdoc/images/delete.png +0 -0
- data/rdoc/images/find.png +0 -0
- data/rdoc/images/loadingAnimation.gif +0 -0
- data/rdoc/images/macFFBgHack.png +0 -0
- data/rdoc/images/package.png +0 -0
- data/rdoc/images/page_green.png +0 -0
- data/rdoc/images/page_white_text.png +0 -0
- data/rdoc/images/page_white_width.png +0 -0
- data/rdoc/images/plugin.png +0 -0
- data/rdoc/images/ruby.png +0 -0
- data/rdoc/images/tag_blue.png +0 -0
- data/rdoc/images/tag_green.png +0 -0
- data/rdoc/images/transparent.png +0 -0
- data/rdoc/images/wrench.png +0 -0
- data/rdoc/images/wrench_orange.png +0 -0
- data/rdoc/images/zoom.png +0 -0
- data/rdoc/index.html +89 -21
- data/rdoc/js/darkfish.js +153 -0
- data/rdoc/js/jquery.js +18 -0
- data/rdoc/js/navigation.js +142 -0
- data/rdoc/js/search.js +94 -0
- data/rdoc/js/search_index.js +1 -0
- data/rdoc/js/searcher.js +228 -0
- data/rdoc/lib/ssn_validator/models/death_master_file_loader_rb.html +95 -0
- data/rdoc/lib/ssn_validator/models/death_master_file_rb.html +95 -0
- data/rdoc/lib/ssn_validator/models/ssn_high_group_code_loader_rb.html +95 -0
- data/rdoc/lib/ssn_validator/models/ssn_high_group_code_rb.html +95 -0
- data/rdoc/lib/ssn_validator/models/ssn_validator_rb.html +95 -0
- data/rdoc/lib/ssn_validator/ntis_rb.html +95 -0
- data/rdoc/lib/ssn_validator_rb.html +95 -0
- data/rdoc/rdoc.css +543 -0
- data/rdoc/table_of_contents.html +107 -0
- data/ssn_validator.gemspec +54 -14
- metadata +56 -20
data/History.txt
CHANGED
data/Rakefile
CHANGED
@@ -1,60 +1,61 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rake'
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
gemspec.
|
9
|
-
gemspec.
|
10
|
-
gemspec.
|
11
|
-
gemspec.
|
12
|
-
gemspec.
|
13
|
-
gemspec.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
test.
|
26
|
-
test.
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
test.
|
34
|
-
test.
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
rdoc.
|
56
|
-
rdoc.
|
57
|
-
rdoc.rdoc_files.include('
|
58
|
-
rdoc.rdoc_files.include('
|
59
|
-
|
60
|
-
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gemspec|
|
8
|
+
gemspec.name = "ssn_validator"
|
9
|
+
gemspec.author = "Kevin Tyll"
|
10
|
+
gemspec.email = "kevintyll@gmail.com"
|
11
|
+
gemspec.homepage = %q{http://kevintyll.git.com/ssn_validator}
|
12
|
+
gemspec.summary = "Validates whether an SSN has likely been issued or not."
|
13
|
+
gemspec.description = "Validates whether an SSN has likely been issued or not."
|
14
|
+
gemspec.post_install_message = File.readlines("PostInstall.txt").join("")
|
15
|
+
end
|
16
|
+
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rake/testtask'
|
24
|
+
Rake::TestTask.new(:test) do |test|
|
25
|
+
test.libs << 'test'
|
26
|
+
test.pattern = 'test/test_*.rb'
|
27
|
+
test.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
require 'rcov/rcovtask'
|
32
|
+
Rcov::RcovTask.new do |test|
|
33
|
+
test.libs << 'test'
|
34
|
+
test.pattern = 'test/**/*_test.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
task :rcov do
|
39
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
task :default => :test
|
45
|
+
|
46
|
+
require 'rdoc/task'
|
47
|
+
Rake::RDocTask.new do |rdoc|
|
48
|
+
if File.exist?('VERSION.yml')
|
49
|
+
config = YAML.load(File.read('VERSION.yml'))
|
50
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
51
|
+
else
|
52
|
+
version = ""
|
53
|
+
end
|
54
|
+
|
55
|
+
rdoc.rdoc_dir = 'rdoc'
|
56
|
+
rdoc.title = "ssn_validator #{version}"
|
57
|
+
rdoc.rdoc_files.include('README*')
|
58
|
+
rdoc.rdoc_files.include('LICENSE*')
|
59
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
60
|
+
end
|
61
|
+
|
data/VERSION.yml
CHANGED
@@ -10,8 +10,8 @@ class DeathMasterFileLoader
|
|
10
10
|
# as_of is a string in the formatt YYYY-MM-DD for which the file data is accurate.
|
11
11
|
def initialize(path_or_url, file_as_of)
|
12
12
|
@file_path_or_url = path_or_url
|
13
|
-
@file_as_of
|
14
|
-
valid?{|status| yield status if block_given?}
|
13
|
+
@file_as_of = file_as_of
|
14
|
+
valid? { |status| yield status if block_given? }
|
15
15
|
end
|
16
16
|
|
17
17
|
def valid?
|
@@ -23,7 +23,7 @@ class DeathMasterFileLoader
|
|
23
23
|
if File.exists?(@file_path_or_url)
|
24
24
|
@download_file = File.open(@file_path_or_url)
|
25
25
|
elsif URI.parse(@file_path_or_url).kind_of?(URI::HTTP)
|
26
|
-
@download_file = File.open(get_file_from_web{|status| yield status if block_given?})
|
26
|
+
@download_file = File.open(get_file_from_web { |status| yield status if block_given? })
|
27
27
|
else
|
28
28
|
raise(Errno::ENOENT, @file_path_or_url)
|
29
29
|
end
|
@@ -35,26 +35,29 @@ class DeathMasterFileLoader
|
|
35
35
|
puts "Converting file to csv format for Mysql import. This could take several minutes."
|
36
36
|
yield "Converting file to csv format for Mysql import. This could take several minutes." if block_given?
|
37
37
|
|
38
|
-
csv_file = convert_file_to_csv{|status| yield status if block_given?}
|
38
|
+
csv_file = convert_file_to_csv { |status| yield status if block_given? }
|
39
39
|
|
40
|
-
bulk_mysql_update(csv_file){|status| yield status if block_given?}
|
40
|
+
bulk_mysql_update(csv_file) { |status| yield status if block_given? }
|
41
41
|
else
|
42
|
-
active_record_file_load{|status| yield status if block_given?}
|
42
|
+
active_record_file_load { |status| yield status if block_given? }
|
43
43
|
end
|
44
44
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def get_file_from_web
|
48
|
-
uri
|
48
|
+
uri = URI.parse(@file_path_or_url)
|
49
49
|
|
50
50
|
request = Net::HTTP::Get.new(uri.request_uri)
|
51
51
|
request.basic_auth(SsnValidator::Ntis.user_name, SsnValidator::Ntis.password)
|
52
52
|
|
53
|
-
|
54
|
-
|
53
|
+
proxy_addr, proxy_port = ENV['http_proxy'].gsub("http://", "").split(/:/) if ENV['http_proxy']
|
54
|
+
proxy_user, proxy_pass = uri.userinfo.split(/:/) if uri.userinfo
|
55
|
+
http = Net::HTTP::Proxy(proxy_addr, proxy_port, proxy_user, proxy_pass).new(uri.host, uri.port)
|
56
|
+
|
57
|
+
http.use_ssl = (uri.port == 443)
|
55
58
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
56
59
|
|
57
|
-
csv_file
|
60
|
+
csv_file = Tempfile.new(@file_path_or_url.split('/').last) # create temp file for the raw file.
|
58
61
|
http.request(request) do |res|
|
59
62
|
raise(ArgumentError, "Invalid URL: #{@file_path_or_url}") if res.kind_of?(Net::HTTPNotFound)
|
60
63
|
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 res.kind_of?(Net::HTTPUnauthorized)
|
@@ -75,14 +78,14 @@ class DeathMasterFileLoader
|
|
75
78
|
#It starts with the last file loaded, and loads each
|
76
79
|
#missing file in sequence up to the current file.
|
77
80
|
def self.load_update_files_from_web
|
78
|
-
max_as_of
|
79
|
-
run_file_date
|
81
|
+
max_as_of = DeathMasterFile.maximum(:as_of)
|
82
|
+
run_file_date = max_as_of.beginning_of_month.next_month
|
80
83
|
last_file_date = Date.today.beginning_of_month
|
81
84
|
while run_file_date <= last_file_date
|
82
85
|
url = "https://dmf.ntis.gov/dmldata/monthly/MA#{run_file_date.strftime("%y%m%d")}"
|
83
86
|
puts "Loading file #{url}"
|
84
87
|
yield "Loading file #{url}" if block_given?
|
85
|
-
dmf = DeathMasterFileLoader.new(url, run_file_date.strftime("%Y-%m-%d")){|status| yield status if block_given?}
|
88
|
+
dmf = DeathMasterFileLoader.new(url, run_file_date.strftime("%Y-%m-%d")) { |status| yield status if block_given? }
|
86
89
|
dmf.load_file do |status|
|
87
90
|
yield status if block_given?
|
88
91
|
end
|
@@ -96,16 +99,16 @@ class DeathMasterFileLoader
|
|
96
99
|
# Used to convert a packed fixed-length file into csv for mysql import.
|
97
100
|
def convert_file_to_csv
|
98
101
|
|
99
|
-
csv_file
|
102
|
+
csv_file = Tempfile.new("dmf") # create temp file for converted csv formmat.
|
100
103
|
|
101
104
|
|
102
|
-
start
|
103
|
-
timenow
|
105
|
+
start = Time.now
|
106
|
+
timenow = start.to_s(:db)
|
104
107
|
|
105
108
|
@delete_ssns = []
|
106
109
|
|
107
110
|
@download_file.each_with_index do |line, i|
|
108
|
-
action
|
111
|
+
action = record_action(line)
|
109
112
|
attributes_hash = text_to_hash(line)
|
110
113
|
if action == 'D'
|
111
114
|
#keep track of all the records to delete. We'll delete at the end all at once.
|
@@ -114,33 +117,33 @@ class DeathMasterFileLoader
|
|
114
117
|
# empty field for id to be generated by mysql.
|
115
118
|
newline = "``," +
|
116
119
|
# social_security_number
|
117
|
-
|
120
|
+
"`#{attributes_hash[:social_security_number]}`," +
|
118
121
|
# last_name
|
119
|
-
|
122
|
+
"`#{attributes_hash[:last_name]}`," +
|
120
123
|
# name_suffix
|
121
|
-
|
124
|
+
"`#{attributes_hash[:name_suffix]}`," +
|
122
125
|
# first_name
|
123
|
-
|
126
|
+
"`#{attributes_hash[:first_name]}`," +
|
124
127
|
# middle_name
|
125
|
-
|
128
|
+
"`#{attributes_hash[:middle_name]}`," +
|
126
129
|
# verify_proof_code
|
127
|
-
|
130
|
+
"`#{attributes_hash[:verify_proof_code]}`," +
|
128
131
|
# date_of_death - need YYYY-MM-DD.
|
129
|
-
|
132
|
+
"`#{attributes_hash[:date_of_death]}`," +
|
130
133
|
# date_of_birth - need YYYY-MM-DD.
|
131
|
-
|
134
|
+
"`#{attributes_hash[:date_of_birth]}`," +
|
132
135
|
# state_of_residence - must be code between 01 and 65 or else nil.
|
133
|
-
|
136
|
+
"`#{attributes_hash[:state_of_residence]}`," +
|
134
137
|
# last_known_zip_residence
|
135
|
-
|
138
|
+
"`#{attributes_hash[:last_known_zip_residence]}`," +
|
136
139
|
# last_known_zip_payment
|
137
|
-
|
140
|
+
"`#{attributes_hash[:last_known_zip_payment]}`," +
|
138
141
|
# created_at
|
139
|
-
|
142
|
+
"`#{timenow}`," +
|
140
143
|
# updated_at
|
141
|
-
|
144
|
+
"`#{timenow}`," +
|
142
145
|
# as_of
|
143
|
-
|
146
|
+
"`#{attributes_hash[:as_of]}`" +"\n"
|
144
147
|
|
145
148
|
csv_file.syswrite newline
|
146
149
|
if (i % 25000 == 0) && (i > 0)
|
@@ -162,7 +165,7 @@ class DeathMasterFileLoader
|
|
162
165
|
yield 'Importing file into database. This could take many minutes.' if block_given?
|
163
166
|
|
164
167
|
@download_file.each_with_index do |line, i|
|
165
|
-
action
|
168
|
+
action = record_action(line)
|
166
169
|
attributes_hash = text_to_hash(line)
|
167
170
|
if action == 'D'
|
168
171
|
DeathMasterFile.destroy_all(['social_security_number = ?', attributes_hash[:social_security_number]])
|
@@ -239,18 +242,18 @@ class DeathMasterFileLoader
|
|
239
242
|
|
240
243
|
def text_to_hash(line)
|
241
244
|
|
242
|
-
{:as_of
|
243
|
-
:social_security_number
|
244
|
-
:last_name
|
245
|
-
:name_suffix
|
246
|
-
:first_name
|
247
|
-
:middle_name
|
248
|
-
:verify_proof_code
|
249
|
-
:date_of_death
|
250
|
-
:date_of_birth
|
245
|
+
{:as_of => @file_as_of.to_date.to_s(:db),
|
246
|
+
:social_security_number => line[1, 9].to_s.strip,
|
247
|
+
:last_name => line[10, 20].to_s.strip,
|
248
|
+
:name_suffix => line[30, 4].to_s.strip,
|
249
|
+
:first_name => line[34, 15].to_s.strip,
|
250
|
+
:middle_name => line[49, 15].to_s.strip,
|
251
|
+
:verify_proof_code => line[64, 1].to_s.strip,
|
252
|
+
:date_of_death => (Date.strptime(line[65, 8].to_s.strip, '%m%d%Y') rescue nil),
|
253
|
+
:date_of_birth => (Date.strptime(line[73, 8].to_s.strip, '%m%d%Y') rescue nil),
|
251
254
|
# - must be code between 01 and 65 or else nil.
|
252
|
-
:state_of_residence
|
255
|
+
:state_of_residence => (line[81, 2].to_s.strip.between?('01', '65') ? line[81, 2].to_s.strip : nil),
|
253
256
|
:last_known_zip_residence => line[83, 5].to_s.strip,
|
254
|
-
:last_known_zip_payment
|
257
|
+
:last_known_zip_payment => line[88, 5].to_s.strip}
|
255
258
|
end
|
256
259
|
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
6
|
+
|
7
|
+
<title>Class: DeathMasterFile</title>
|
8
|
+
|
9
|
+
<link type="text/css" media="screen" href="./rdoc.css" rel="stylesheet">
|
10
|
+
|
11
|
+
<script type="text/javascript">
|
12
|
+
var rdoc_rel_prefix = "./";
|
13
|
+
</script>
|
14
|
+
|
15
|
+
<script type="text/javascript" charset="utf-8" src="./js/jquery.js"></script>
|
16
|
+
<script type="text/javascript" charset="utf-8" src="./js/navigation.js"></script>
|
17
|
+
<script type="text/javascript" charset="utf-8" src="./js/search_index.js"></script>
|
18
|
+
<script type="text/javascript" charset="utf-8" src="./js/search.js"></script>
|
19
|
+
<script type="text/javascript" charset="utf-8" src="./js/searcher.js"></script>
|
20
|
+
<script type="text/javascript" charset="utf-8" src="./js/darkfish.js"></script>
|
21
|
+
|
22
|
+
|
23
|
+
<body id="top" class="class">
|
24
|
+
<nav id="metadata">
|
25
|
+
<nav id="home-section" class="section">
|
26
|
+
<h3 class="section-header">
|
27
|
+
<a href="./index.html">Home</a>
|
28
|
+
<a href="./table_of_contents.html#classes">Classes</a>
|
29
|
+
<a href="./table_of_contents.html#methods">Methods</a>
|
30
|
+
</h3>
|
31
|
+
</nav>
|
32
|
+
|
33
|
+
|
34
|
+
<nav id="search-section" class="section project-section" class="initially-hidden">
|
35
|
+
<form action="#" method="get" accept-charset="utf-8">
|
36
|
+
<h3 class="section-header">
|
37
|
+
<input type="text" name="search" placeholder="Search" id="search-field"
|
38
|
+
title="Type to search, Up and Down to navigate, Enter to load">
|
39
|
+
</h3>
|
40
|
+
</form>
|
41
|
+
|
42
|
+
<ul id="search-results" class="initially-hidden"></ul>
|
43
|
+
</nav>
|
44
|
+
|
45
|
+
|
46
|
+
<div id="file-metadata">
|
47
|
+
<nav id="file-list-section" class="section">
|
48
|
+
<h3 class="section-header">Defined In</h3>
|
49
|
+
<ul>
|
50
|
+
<li>lib/ssn_validator/models/death_master_file.rb
|
51
|
+
</ul>
|
52
|
+
</nav>
|
53
|
+
|
54
|
+
|
55
|
+
</div>
|
56
|
+
|
57
|
+
<div id="class-metadata">
|
58
|
+
|
59
|
+
<nav id="parent-class-section" class="section">
|
60
|
+
<h3 class="section-header">Parent</h3>
|
61
|
+
|
62
|
+
<p class="link">ActiveRecord::Base
|
63
|
+
|
64
|
+
</nav>
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
</div>
|
69
|
+
|
70
|
+
<div id="project-metadata">
|
71
|
+
<nav id="fileindex-section" class="section project-section">
|
72
|
+
<h3 class="section-header">Pages</h3>
|
73
|
+
|
74
|
+
<ul>
|
75
|
+
|
76
|
+
<li class="file"><a href="./LICENSE.html">LICENSE</a>
|
77
|
+
|
78
|
+
<li class="file"><a href="./README_rdoc.html">README</a>
|
79
|
+
|
80
|
+
</ul>
|
81
|
+
</nav>
|
82
|
+
|
83
|
+
<nav id="classindex-section" class="section project-section">
|
84
|
+
<h3 class="section-header">Class and Module Index</h3>
|
85
|
+
|
86
|
+
<ul class="link-list">
|
87
|
+
|
88
|
+
<li><a href="./SsnValidator.html">SsnValidator</a>
|
89
|
+
|
90
|
+
<li><a href="./SsnValidator/Ntis.html">SsnValidator::Ntis</a>
|
91
|
+
|
92
|
+
<li><a href="./SsnValidator/Ssn.html">SsnValidator::Ssn</a>
|
93
|
+
|
94
|
+
<li><a href="./DeathMasterFile.html">DeathMasterFile</a>
|
95
|
+
|
96
|
+
<li><a href="./DeathMasterFileLoader.html">DeathMasterFileLoader</a>
|
97
|
+
|
98
|
+
<li><a href="./SsnHighGroupCode.html">SsnHighGroupCode</a>
|
99
|
+
|
100
|
+
<li><a href="./SsnHighGroupCodeLoader.html">SsnHighGroupCodeLoader</a>
|
101
|
+
|
102
|
+
</ul>
|
103
|
+
</nav>
|
104
|
+
|
105
|
+
</div>
|
106
|
+
</nav>
|
107
|
+
|
108
|
+
<div id="documentation">
|
109
|
+
<h1 class="class">class DeathMasterFile</h1>
|
110
|
+
|
111
|
+
<div id="description" class="description">
|
112
|
+
|
113
|
+
</div><!-- description -->
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
<section id="5Buntitled-5D" class="documentation-section">
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
<!-- Methods -->
|
128
|
+
|
129
|
+
</section><!-- 5Buntitled-5D -->
|
130
|
+
|
131
|
+
</div><!-- documentation -->
|
132
|
+
|
133
|
+
|
134
|
+
<footer id="validator-badges">
|
135
|
+
<p><a href="http://validator.w3.org/check/referer">[Validate]</a>
|
136
|
+
<p>Generated by <a href="https://github.com/rdoc/rdoc">RDoc</a> 3.11.
|
137
|
+
<p>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish Rdoc Generator</a> 3.
|
138
|
+
</footer>
|
139
|
+
|