Created
February 21, 2011 17:45
-
-
Save bnadlerjr/837405 to your computer and use it in GitHub Desktop.
Example executable resume in Ruby.
This file contains hidden or 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
require "erb" | |
require "ostruct" | |
require "optparse" | |
options = {} | |
OptionParser.new do |opts| | |
opts.banner = <<-DESC | |
Usage: | |
ruby resume.rb [options] | |
Examples: | |
ruby resume.rb # => Outputs resume to STDOUT | |
ruby resume.rb --format HTML > resume.html # => Outputs resume to an HTML file. | |
DESC | |
opts.on("-f", "--format [TEXT|HTML]", "Set the output format. Default is TEXT.") do |f| | |
options[:format] = f ? f.downcase.to_sym : :text | |
end | |
end.parse! | |
# Custom extensions to be mixed into +String+. | |
module StringExt | |
# Wraps a string to a certain width. | |
# | |
# Options: | |
# | |
# length:: | |
# Number of chars to wrap the string. Default is 70. | |
# | |
# indent_first:: | |
# If +true+, indents the first line of the string. Default is +false+. | |
# | |
# indent:: | |
# Indicates indent level. Default is ' '. | |
def wrap(options={}) | |
indent_first = options[:indent_first] || false | |
length = options[:length] || 70 | |
indent = options[:indent] || ' ' | |
return self if self.length < length | |
# RegEx is based on info from here: | |
# http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/ | |
indent_first ? sub = "#{indent}\\1\\2\n" : sub = "\\1\\2\n#{indent}" | |
self.gsub(/(.{1,#{length}})(?: +|$\n?)|(.{1,#{length}})/, sub) | |
end | |
end | |
class String; include StringExt; end | |
# Format templates are located at the end of this file. Each format is | |
# delimited by it's name, followed by the template. For example: | |
# @@ TEXT @@ | |
# <text template goes here...> | |
# | |
# Templates are loaded into the +FORMATTERS+ hash where the name is the key and | |
# a Proc that will execute the template is the value. | |
templates = DATA.read.split(/^@@ /).map { |format| format.split(/ @@\n/) } | |
FORMATTERS = {} | |
templates.each do |tpl| | |
name = tpl[0].downcase.to_sym | |
FORMATTERS[name] = lambda { |resume| ERB.new(tpl[1], nil, '-').result } unless tpl.empty? | |
end | |
# Stores information regarding an individual's resume. Inherits from | |
# +OpenStruct+ so that resume sections can be dynamically created as needed. | |
class Resume < OpenStruct | |
# Initializes a new +Resume+ object. If invoked with a block the new +Resume+ | |
# instance is passed to the block. | |
# | |
# Example: | |
# Resume.new do |r| | |
# # r is the new instance | |
# end | |
def initialize(&block) | |
super | |
yield self if block_given? | |
end | |
# Renders the +Resume+ using the given format. The default format is +:text+. | |
# Raises an +ArgumentError+ if the format specified cannot be found in | |
# +FORMATTERS+. | |
def render(format=:text) | |
raise ArgumentError, | |
"Unrecognized format(#{format})." unless FORMATTERS.has_key?(format) | |
FORMATTERS.fetch(format).call(self) | |
end | |
end | |
# My Resume | |
resume = Resume.new do |r| | |
r.contact = { | |
:name => 'Bob Nadler, Jr.', | |
:city => 'Fords', :state => 'NJ', | |
:phone => '(732) 707-1044', | |
:email => '[email protected]', | |
:website => 'http://bobnadler.com' | |
} | |
r.technical_skills = { | |
'Ruby' => | |
"3.5 years. Built a collateral analysis tool for a financial services company using Ruby and Ruport library. Contributed a patch to Ruport library for dealing with pivot tables. Wrote Rubox, a Ruby client for the Box.net API. Produced Ruby scripts to 'glue' together various enterprise systems.", | |
'Rails / Sinatra' => | |
"1 year. Constructed an intranet application for a startup energy financial services company using Rails. Used HAML / SASS for UI, Shoulda & Mocha for testing, Cucumber for acceptance tests and Capistrano for deployment. Hosted on Slicehost. Launched a free web application written in Sinatra for tracking car fuel economy. Uses ZeepMobile for SMS messaging, omniauth for authentication. Deployed using Heroku. Wrote an internal Rails application for tracking project tasks and estimates. Implemented evidence based scheduling to create project timeline projections which increased project visibility and accuracy of estimates. Utilized the Ruport library for generating graphs and reports.", | |
'JavaScript' => | |
"<1 year. Used Prototype / script.acoul.us to enhance user experience in a Rails-based intranet application. Currently developing a graphing library based on jQuery and Raphael.js for a financial services dashboard application.", | |
'HTML / CSS' => | |
"10+ years. Designed various web pages for business colleagues and personal projects.", | |
'.NET (C# and VB.NET) / MS Access / VBA' => | |
"7 years. Built and deployed ASP.NET web applications. Replaced large Excel spreadsheets that contained complex logic with MS Access databases. Created and maintained numerous Excel macros that connected to various systems.", | |
'Miscellaneous' => | |
"Linux, OS X, Windows; Vim, Textmate, Visual Studio; Git, Subversion; Rake, NAnt; Watin / Watir, NMock, NUnit; Basic Lease Accounting, Risk Equity, Portfolio Funding, Asset Based Lending; C, Pascal; XML, Web Services (REST & SOAP); MS SQL Server, MySQL, SQLite; MS Office (Word, Excel, PowerPoint, InfoPath); SAP BEx" | |
} | |
r.interpersonal_skills = { | |
'Project Management' => | |
"Consistently steered software projects from inception to final deployment using various agile methodologies. Involved in all aspects of the process from working with end users to designing user interfaces and writing code. Managed software projects with 1-4 developers, with budgets up to $1MM.", | |
'Communication Skills' => | |
"Ability to translate business needs and ideas into viable IT solutions. Regularly act as the \"go-between\" for the business and IT groups. Trained employees in the use of various software applications." | |
} | |
r.work_history = [ | |
{ :position => 'Freelance Ruby Developer', | |
:company => 'Bob Nadler', | |
:period => 'OCT 2009 - Present', | |
:accomplishments => "Designed, implemented and deployed a Ruby on Rails web application for a small financial services company. Launched a free web application written in Sinatra for tracking a car's fuel economy. Contributed a patch to Ruport library. Wrote a Ruby client for the Box.net API." }, | |
{ :position => 'Project Manager', | |
:company => 'Siemens Financial Services', | |
:period => 'AUG 2007 - Present', | |
:accomplishments => "Acted as primary liaison between the Working Capital Finance group and the IT group for the ABL \"Dashboard\" and Healthcare Collateral system projects. Involved in the hiring of IT contractors, writing specifications and testing. Designed and implemented a web-based change request form with workflow for the ABL group using ASP.NET; web-based version replaced an unreliable paper process. Planned and implemented a collateral analysis tool using Ruby and the Ruport library which replaced an error prone manual process that relied on Excel. Designed and implemented a Buyout / Rollover Request tool using Excel which replaced a paper-based version. Integrated the tool with a legacy database and added workflow support using VBA. Managed various small IT related projects for the Working Capital Finance group." }, | |
{ :position => 'Risk Reporting Manager', | |
:company => 'Siemens Financial Services', | |
:period => 'JAN 2006 - JUL 2007', | |
:accomplishments => "Designed, implemented and maintained Excel spreadsheet tools for managing the monthly Risk Report as well as various ad hoc reports. Acted as primary contact for Risk Control, Munich for all issues concerning the AWARD data warehouse, including the coordination of IT resources both in the U.S. and Munich. Automated the generation of the monthly Compliance Report saving time and eliminating the need for manual calculations. Supported the SFS Treasury functions by analyzing manual processes and implementing automated solutions using MS Office and various Ruby scripts." }, | |
{ :position => 'Syndications Account Manager', | |
:company => 'Siemens Financial Services', | |
:period => 'JUL 2003 - DEC 2006', | |
:accomplishments => "Designed, implemented and maintained a tool named SynTrack for the Healthcare Syndications Group using MS Access. The tool provided existing portfolio analysis, potential sale analysis, bid analysis, financial impact analysis, and syndication activity tracking. These tasks were previously performed manually and were time intensive. Provided ad hoc and monthly reports using MS Access & MS Excel for the Healthcare Group which gave the group business intelligence information that was previously not available. Planned and implemented a Financial Statement database in MS Access for the Healthcare Credit and Syndications Groups which allows the groups to track customer financial information. Acted as Information Security Advisor for the Healthcare group working with the IT department on security and business continuity planning issues." }, | |
{ :position => 'End of Term Assistant', | |
:company => 'Siemens Financial Services', | |
:period => 'JAN 2002 - JAN 2003', | |
:accomplishments => "Streamlined the End-of-Term process for Siemens Financial using MS Excel and Word to create mail merges and various forms which reduced the processing time. Created an MS Access database to automate certain reports that previously had been done in Excel. This database was also used to create the reports for Siemens Financial Business Unit Review presentations." }, | |
{ :position => 'Asset Protection Associate', | |
:company => 'Sears', | |
:period => 'MAY 1996 - OCT 2000', | |
:accomplishments => "Used MS Office to create forms and spreadsheets to track shoplifting, internal theft, accident trends and operational controls, which improved the impact of the Sears Asset Protection Department on store inventory loss. Researched, re-organized and updated store policy guidelines and procedures manuals for two Sears stores. This resulted in better inventory recovery due to stricter operational controls." } | |
] | |
end | |
puts resume.render(options[:format] || :text) | |
__END__ | |
# FORMAT TEMPLATES | |
@@ TEXT @@ | |
<%= resume.contact[:name] %> | |
<%= resume.contact[:address] %> | |
<%= resume.contact[:city] %>, <%= resume.contact[:state] %> | |
<%= resume.contact[:email] %> | |
<%= resume.contact[:website] %> | |
------------------------------------------------------------------------ | |
TECHNICAL SKILLS | |
<% resume.technical_skills.each do |k,v| -%> | |
* <%= "#{k}: #{v}".wrap %> | |
<% end -%> | |
INTERPERSONAL SKILLS | |
<% resume.interpersonal_skills.each do |k,v| -%> | |
* <%= "#{k}: #{v}".wrap %> | |
<% end -%> | |
WORK HISTORY | |
<% resume.work_history.each do |work| -%> | |
<%= work[:position] %> - <%= work[:company] %> (<%= work[:period] %>) | |
<%= work[:accomplishments].wrap(:indent_first => true) %> | |
<% end -%> | |
@@ HTML @@ | |
<html> | |
<head> | |
<style> | |
/* reset */ | |
html, body, div, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, big, cite, code,del, dfn, em, font, img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,dl, dt, dd, ol, ul, li,fieldset, form, label, legend,table, caption, tbody, tfoot, thead, tr, th, td { margin: 0;padding: 0;border: 0;outline: 0;font-weight: inherit;font-style: inherit;font-size: 100%;font-family: inherit;vertical-align: baseline} | |
:focus {outline: 0;} | |
body {line-height: 1;color: black;background: white} | |
ol, ul { list-style: none; } | |
table { border-collapse: separate; border-spacing: 0; } | |
caption, th, td { text-align: left; font-weight: normal; } | |
blockquote:before, blockquote:after, q:before, q:after { content: ""; } | |
blockquote, q { quotes: "" ""; } | |
/* layout */ | |
body { width: 600px; margin: auto } | |
/* typography */ | |
body { font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; } | |
h1 { font-size: 2.5em; margin: 1em 0 0.5em 0 } | |
h2 { font-size: 1.5em; margin: 1em 0 0.5em 0 } | |
strong { font-weight: bold; } | |
ol, ul { margin: 0 1em 1em 0; padding-left: 2.5em; } | |
ul { list-style-type: disc; } | |
ul li { margin: 0 0 1em 0; line-height: 1.25em; } | |
ol li { margin: 0 0 1em 0; line-height: 1.25em; } | |
dl { margin: 0 0 1em 0; } | |
dt { font-weight: bold; line-height: 1.25em; } | |
dd { margin: 0 1em 1em 0; padding-left: 2.5em; line-height: 1.25em; } | |
</style> | |
</head> | |
<body> | |
<h1><%= resume.contact[:name] %></h1> | |
<address> | |
<%= resume.contact[:address] %><br /> | |
<%= resume.contact[:city] %>, <%= resume.contact[:state] %> <%= resume.contact[:postal] %><br /> | |
<%= resume.contact[:email] %><br /> | |
<%= resume.contact[:website] %> | |
</address> | |
<hr /> | |
<h2>TECHNICAL SKILLS</h2> | |
<ul> | |
<% resume.technical_skills.each do |k,v| -%> | |
<li><%= "<strong>#{k}:</strong> #{v}".wrap %></li> | |
<% end -%> | |
</ul> | |
<h2>INTERPERSONAL SKILLS</h2> | |
<ul> | |
<% resume.interpersonal_skills.each do |k,v| -%> | |
<li><%= "<strong>#{k}:</strong> #{v}".wrap %></li> | |
<% end -%> | |
</ul> | |
<h2>WORK HISTORY</h2> | |
<dl> | |
<% resume.work_history.each do |work| -%> | |
<dt><%= work[:position] %> - <%= work[:company] %> (<%= work[:period] %>)</dt> | |
<dd><%= work[:accomplishments].wrap(:indent_first => true) %></dd> | |
<% end -%> | |
</dl> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment