Last active
December 14, 2015 06:29
-
-
Save laod/5043194 to your computer and use it in GitHub Desktop.
Code snippet from a ruby project that maps data from our directories and sis warehouse to csv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby | |
require 'ldap' | |
require 'pg' | |
require 'csv' | |
# because empty isn't false, that's why | |
class String | |
def presence | |
self.empty? ? nil : self | |
end | |
end | |
# HACK: we want to pick from the available addresses in order. So make sure we get the requested | |
# field(s) for all of them PLUS line_1 which we will use to decide | |
def address_helper(fields) | |
(["line_1"] | [fields].flatten).map{|f| ['rma','local','home'].map{|a| "#{a}_address_#{f}"}}.flatten | |
end | |
# decide which address to use, expects the first three values from address_helper | |
# rma_address_line_1, local_address_line_1, home_address_line_1 | |
def which(addrs) | |
addrs.index((addrs[0].presence || addrs[1].presence || addrs[2].presence)) || 0 | |
end | |
# kill me | |
map = [ | |
#general | |
{name: "Patient Control ID", value: nil}, | |
{name: "SSN", value: nil}, | |
{name: "Other ID", source: :ldap, source_name: "datatelid"}, | |
{name: "Last Name", source: :ldap, source_name: "sn"}, | |
{name: "First Name", source: :ldap, source_name: "givenName"}, | |
{name: "Middle Initial", source: :ods, source_name: "middle", mapper: Proc.new {|v| v[0]}}, | |
{name: "Sex", source_name: "gender", source: :ods}, | |
{name: "Address", source: :ods, source_name: address_helper(["line_1","line_2"]), mapper: Proc.new{|v| t = which v[0..2]; [v[t], v[t+3]].reject(&:empty?).join " "}}, | |
{name: "City", source_name: address_helper("city"), source: :ods, mapper: Proc.new{|v| v[which(v[0..2]) + 3]}}, | |
{name: "State", source_name: address_helper("state"), source: :ods, mapper: Proc.new{|v| t = v[which(v[0..2]) + 3]; t.empty? ? 'NA' : t}}, | |
{name: "Zip Code", source_name: address_helper("zip"), source: :ods, mapper: Proc.new{|v| t = v[which(v[0..2]) + 3]; t.delete '-'}}, | |
{name: "Home Phone", value: nil}, | |
{name: "Work Phone", source_name: "officePhoneNumber", source: :ldap, mapper: Proc.new{|v| v.gsub /[^0-9]/, ""}}, | |
{name: "Cell Phone", source_name: "cell_phone", source: :ods, mapper: Proc.new{|v| v.gsub /[^0-9]/, ""}}, | |
{name: "Date of Birth", source_name: "birthday", source: :ods, mapper: Proc.new {|v| [1,2,0].map{|i| v.split('-')[i]}.join('/')}}, | |
{name: "Marital Status", source_name: "marital_status", source: :ods, mapper: Proc.new {|v| {"M" => 1, "S" => 2, "" => 7}[v] }}, | |
{name: "Employment", source_name: "employment_status_code", source: :ods, mapper: Proc.new {|v| {'FT' => 1, 'PT' => 2, 'AF' => 7, 'VF' => 7, 'T' => 7, '7' => 7, '' => 7}[v]}}, | |
{name: "Employer Code", value: "TU"}, | |
{name: "Email Address", source: :ldap, source_name: "primaryMail"}, | |
{name: "Eligibility", value: 2}, | |
# students | |
{name: "Campus Address", source_name: "rma_address_line_1", source: :ods}, | |
{name: "Permanent Address", source: :ods, source_name: "home_address_line_1"}, | |
{name: "Permanent City", source_name: "home_address_city", source: :ods}, | |
{name: "Permanent State", source_name: "home_address_state", source: :ods}, | |
{name: "Permanent Zip Code", source_name: "home_address_zip", source: :ods, mapper: Proc.new{|v| v.delete '-'}}, | |
{name: "Permanent Country", source_name: "home_address_country", source: :ods}, | |
{name: "Permanent Phone", source_name: "home_phone", source: :ods, mapper: Proc.new{|v| v.gsub /[^0-9]/, ""}}, | |
{name: "Foreign Student", source_name: "foreign_student", source: :ods, mapper: Proc.new{|v| ['','true'].index v}}, | |
{name: "Visa Type", source_name: "visa_type", source: :ods}, | |
{name: "Major", source: :ods, source_name: "major1"}, | |
{name: "Standing", source_name: "academic_level", source: :ods}, | |
{name: "Class", source_name: "class", source: :ods}, | |
{name: "Enrollment Date", source_name: "start_term", source: :ods}, | |
{name: "Student Status", source_name: "course_load", source: :ods}, | |
{name: "School", value: "TU"}, | |
{name: "Residency", source_name: "room_assignment", source: :ods, mapper: Proc.new {|v| v.empty? ? 2 : 1}}, | |
# misc | |
{name: "Race", value: 8}, | |
{name: "Ethnicity", value: nil}, | |
{name: "EmerName", source_name: "emergency_contact_name", source: :ods}, | |
{name: "EmerPhone1", source_name: "emergency_contact_phone", source: :ods, mapper: Proc.new{|v| v.gsub /[^0-9]/, ""}}, | |
{name: "EmerRelationship", value: nil}, | |
] | |
# get the list of ldap attrs we want and ensure it contains datatelid | |
@attrs = map.select{|f| f[:source] == :ldap} | |
.map{|f| f[:source_name] || f[:name]} | ['datatelid'] | |
SECRETS!!1 | |
def lookup(uid) | |
l = @dir.search2 @base, LDAP::LDAP_SCOPE_SUBTREE, 'uid='+uid, @attrs | |
# TODO: blow up if more than one | |
r = {} | |
r[:ldap] = l[0].each{|k,v| l[0][k] = v[0]} | |
r[:ods] = {} | |
res = @vault.exec("select did,name,value from namevalue where did='#{r[:ldap]['datatelid']}'") | |
res.each do |i| | |
r[:ods][i['name']] = i['value'] | |
end | |
p r | |
r | |
end | |
# HACK: I hate single-value arrays | |
class Array | |
def value_or_values | |
self.count == 1 ? self.first : self | |
end | |
end | |
# comparable to Reg Braithwaite's Object#into, tells an object to pass itself to | |
# a block for chaining goodness. | |
class Object | |
def mutate | |
yield(self) | |
end | |
end | |
CSV.open("medicat.psv", "wb", {col_sep: "|", row_sep: "\r\n", headers: true}) do |csv| | |
csv << map.map {|f| f[:name]} | |
ARGF.each do |uid| | |
uid.strip! | |
p uid | |
r = lookup uid | |
csv << map.map do |field| | |
if field.include? :value | |
field[:value] | |
else | |
# name(s) -> value(s) -> transformed value(s) -- driven by the map array | |
# HACK: [].flatten turns singles into arrays without messing arrays up | |
# would have been easier but gross to regularize on arrays | |
[(field[:source_name] || field[:name])].flatten | |
.map{|f| r[field[:source]][f] || ''}.value_or_values | |
.mutate{|o| (field[:mapper] || Proc.new {|v| v}).call o} | |
end | |
end.map{|i| i == "" ? nil : i} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment