ssn_validator 1.0.9 → 1.0.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|