resume 0.0.1

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/README ADDED
@@ -0,0 +1,49 @@
1
+ == The Ruby Based Ruby Resume' Generator
2
+ This is a fun little project for defining your resume in Ruby. You say your a Rubyist, but is your resume written in a DSL? I didn't think so! Using the Ruby Resume' Generator, you too can be a total geek!
3
+
4
+ == Example
5
+ # ruby_coder.rb
6
+ class RubyCoder
7
+ include Resume
8
+ contact :email => %w(ruby coder net), :phone => %w(800 444 3333)
9
+ attended "XYZU", :in => "Gemology", :with => "PHD", :graduated => "1999"
10
+ worked :at => "Gem Cutting, Inc.", :description => "cut all kinds of rubies", :position => "cuter", :tenure => 2008
11
+ built %w(ruby-cuts.tv)
12
+ using %w(ruby haml datamapper)
13
+ practicing %w(agile bdd juggling)
14
+ story %w(I'm a ruby coder of some skill and whatnot. You should hire be because I'm cool.)
15
+ end
16
+
17
+ Then, with this gem installed you can pop out a slick little resume'
18
+
19
+ > resume ruby_coder.rb
20
+
21
+ Ruby Coder
22
+ ruby@coder.net 800.444.3333
23
+ --------------------------------------------------------------------------------
24
+ Attended XYZU Gemology for PHD
25
+ --------------------------------------------------------------------------------
26
+ Worked at Gem Cutting, Inc. as a cuter 2008
27
+ cut all kinds of rubies
28
+ --------------------------------------------------------------------------------
29
+ Sites
30
+ ruby-cuts.tv
31
+ --------------------------------------------------------------------------------
32
+ Technologies
33
+ ruby - haml - datamapper
34
+ --------------------------------------------------------------------------------
35
+ Practices
36
+ agile - bdd - juggling
37
+ --------------------------------------------------------------------------------
38
+ I'm a ruby coder of some skill and whatnot. You should hire be because I'm cool.
39
+
40
+ You can also write a PDF file by supplying the -pdf parameter
41
+
42
+ > resume examples/ruby_coder.rb -pdf
43
+ Printing PDF to RubyCoder.pdf
44
+
45
+ == Notes
46
+ Feel free to leave any and all of the various sections out. You can call most methods multiple times and the data
47
+ will simply get added to the list of items.
48
+
49
+ If you want a different format, feel free to hack away. If you can't you probably shouldn't be using this anyway.
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+
4
+ require 'optparse'
5
+ require 'open-uri'
6
+ require File.join(File.dirname(__FILE__), '../lib/resume')
7
+ require File.join(File.dirname(__FILE__), '../lib/pdf_printer')
8
+
9
+ options = {}
10
+ opts = OptionParser.new do |opts|
11
+ opts.banner = "Usage: resume [options] <resume location>"
12
+
13
+ opts.on("-pdf", "Create a PDF") do |pdf|
14
+ options[:pdf] = pdf
15
+ end
16
+
17
+ opts.on("-ruby", "Shows the Ruby code to create this resume") do |ruby|
18
+ options[:ruby] = ruby
19
+ end
20
+
21
+ opts.on_tail("-h", "--help", "Show this message") do
22
+ puts opts
23
+ exit
24
+ end
25
+ opts.parse!
26
+ opts
27
+ end
28
+
29
+ if(ARGV.last =~ /^-/ or ARGV.empty?)
30
+ puts opts
31
+ puts "Resume to print must be supplied."
32
+ exit
33
+ end
34
+
35
+ resume_class_string = open(ARGV.last).read
36
+ eval(resume_class_string)
37
+ resume_class_name = resume_class_string.match(/class\s(.*)/)[1]
38
+ resume_class = eval("#{resume_class_name}.new.class")
39
+
40
+ if(options[:ruby])
41
+ puts resume_class_string
42
+ end
43
+
44
+ if(options[:pdf])
45
+ printer = PDFPrinter.new(resume_class)
46
+ puts "Printing PDF to #{printer.filename}"
47
+ printer.print
48
+ else
49
+ resume_class.pretty_print
50
+ end
51
+
@@ -0,0 +1,66 @@
1
+ require 'rubygems'
2
+ require 'prawn'
3
+
4
+ class PDFPrinter
5
+ attr_accessor :resume
6
+
7
+ def initialize(resume)
8
+ self.resume = resume
9
+ end
10
+
11
+ def filename
12
+ "#{self.resume.name}.pdf"
13
+ end
14
+
15
+ def print
16
+ resume = self.resume
17
+ Prawn::Document.generate filename do
18
+ font "Helvetica"
19
+ header margin_box.top_left do
20
+ text resume.my_name, :align => :center, :size => 32
21
+ text resume.print_contact, :align => :center
22
+ stroke_horizontal_rule
23
+ end
24
+ move_down(50)
25
+ if(resume.has_schools?)
26
+ text "Education", :align => :right
27
+ text resume.print_schools, :align => :left
28
+ stroke_horizontal_rule
29
+ end
30
+ if(resume.has_jobs?)
31
+ text "Employment", :align => :right
32
+ text resume.print_jobs, :align => :left
33
+ stroke_horizontal_rule
34
+ end
35
+
36
+ if(resume.has_applications?)
37
+ text "Sites", :align => :right
38
+ text resume.print_array(resume.applications), :align => :center
39
+ stroke_horizontal_rule
40
+ end
41
+
42
+ if(resume.has_technologies?)
43
+ text "Technologies", :align => :right
44
+ text resume.print_array(resume.technologies), :align => :center
45
+ stroke_horizontal_rule
46
+ end
47
+
48
+ if(resume.has_practices?)
49
+ text "Practices", :align => :right
50
+ text resume.print_array(resume.practices), :align => :center
51
+ stroke_horizontal_rule
52
+ end
53
+
54
+ if(resume.has_story?)
55
+ text resume.story_text
56
+ end
57
+
58
+ footer margin_box.bottom_left do
59
+ font "Courier"
60
+ fill_color "999999"
61
+
62
+ text "gem install resume; #{$0} #{$*}", :align => :center, :size => 10
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,154 @@
1
+ module Resume
2
+
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ (base.methods - Object.methods).each do |method|
6
+ base.send(method, Array.new) if method =~ /=$/
7
+ end
8
+ base.contact_info = Hash.new
9
+ base.width = 80 # default width
10
+ end
11
+
12
+ module ClassMethods
13
+ attr_accessor :contact_info, :schools, :jobs, :applications, :technologies, :practices, :width, :story_text
14
+
15
+ def my_name
16
+ self.to_s.gsub(/([A-Z]+)([A-Z][a-z])/,'\1 \2').gsub(/([a-z\d])([A-Z])/,'\1 \2')
17
+ end
18
+
19
+ def contact(opts = {})
20
+ if(email = opts[:email])
21
+ self.contact_info[:email] = email.is_a?(Array) ? email.to_email : (raise Exception.new('Please use an array to define your email address'))
22
+ end
23
+
24
+ if(phone = opts[:phone])
25
+ self.contact_info[:phone] = phone.is_a?(Array) ? phone.to_phone : (raise Exception.new('Please use an array to define your phone number'))
26
+ end
27
+
28
+ end
29
+
30
+ def story(story)
31
+ self.story_text = story.join(" ")
32
+ end
33
+
34
+ # attended "XYZU", :in => "Basket Weaving", :with => "PHD", :graduated => "1999"
35
+ def attended(school, opts = {})
36
+ self.schools << {:name => school, :curriculum => opts[:in], :degree => opts[:with], :graduated => opts[:graduated]}
37
+ end
38
+
39
+ # worked :at => "Acme, Inc.", :description => "bored out of skull", :position => "Monkey", :tenure => 2008
40
+ def worked(opts = {})
41
+ self.jobs << {:company => opts[:at], :description => opts[:description], :position => opts[:position], :tenure => opts[:tenure]}
42
+ end
43
+
44
+ {"built" => "applications", "using" => "technologies", "practicing" => "practices"}.each do |name, accessor|
45
+ class_eval <<-EOV
46
+ def #{name}(args)
47
+ self.#{accessor} = self.#{accessor} + (args.is_a?(Array) ? args : [args])
48
+ end
49
+ EOV
50
+ end
51
+
52
+ def line(width = @width)
53
+ "-".center(width, "-")
54
+ end
55
+
56
+ def pretty_print(out = $>, width = @width)
57
+ print(my_name, out, width, :center)
58
+ print_contact(out, width)
59
+ print(line, out, width)
60
+ print(line, out, width) if print_schools(out, width)
61
+ print(line, out, width) if print_jobs(out, width)
62
+ print(line, out, width) if print_array(applications, "Sites", out, width)
63
+ print(line, out, width) if print_array(technologies, "Technologies", out, width)
64
+ print(line, out, width) if print_array(practices, "Practices", out, width)
65
+ print(story_text, out, width)
66
+ out << "\n"
67
+ end
68
+
69
+ def has_contact_info?
70
+ !contact_info[:email].nil? or !contact_info[:phone].nil?
71
+ end
72
+
73
+ def has_story?
74
+ self.story_text and !self.story_text.empty?
75
+ end
76
+
77
+ %w(schools jobs applications technologies practices story_).each do |name|
78
+ class_eval <<-EOV
79
+ def has_#{name}?
80
+ self.#{name} and !self.#{name}.empty?
81
+ end
82
+ EOV
83
+ end
84
+
85
+ def print_contact(out = "", width = @width)
86
+ row = ""
87
+ row << contact_info[:email] if contact_info[:email]
88
+ row << " " if contact_info[:email] and contact_info[:phone]
89
+ row << contact_info[:phone] if contact_info[:phone]
90
+ print(row, out, width, :center)
91
+ end
92
+
93
+ def print_schools(out = "", width = @width)
94
+ schools.collect { |s|
95
+ row = ""
96
+ row << "Attended #{s[:name]}" if s[:name]
97
+ row << " #{s[:curriculum]}" if s[:curriculum]
98
+ row << " for #{s[:degree]}" if s[:degree]
99
+ row << " graduated #{s[:year]}" if s[:year]
100
+ print(row, out, width, :right)
101
+ }.join("\n")
102
+ end
103
+
104
+ def print_jobs(out = "", width = @width)
105
+ jobs.collect { |j|
106
+ row = ""
107
+ row << "Worked at #{j[:company]}" if j[:company]
108
+ row << " as a #{j[:position]}" if j[:position]
109
+ row << " #{j[:tenure]}" if j[:tenure]
110
+ result = print(row, out, width, :right)
111
+ result += "\n" + print(j[:description], out, width) if j[:description]
112
+ }.join("\n\n")
113
+ end
114
+
115
+ def print_array(array, title = "", out = "", width = @width)
116
+ unless(array.empty?)
117
+ print(title, out, width, :right)
118
+ print(array.join(" - "), out, width)
119
+ end
120
+ end
121
+
122
+ def print(str, out, width, justify = :left)
123
+ if(str.length > width)
124
+ i = str.rindex(' ', width)
125
+ print(str[0, i], out, width, justify)
126
+ print(str[i+1, str.length], out, width, justify)
127
+ elsif(!str.empty?)
128
+ line = str.justify(width, justify)
129
+ out << "\n#{line}"
130
+ line.strip
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ class String
137
+ def justify(width, justify)
138
+ case justify
139
+ when :center: center(width)
140
+ when :left: ljust(width)
141
+ when :right: rjust(width)
142
+ end
143
+ end
144
+ end
145
+
146
+ class Array
147
+ def to_email
148
+ "#{self.first}@#{self[1,size].join('.')}"
149
+ end
150
+
151
+ def to_phone(delimiter = ".")
152
+ self.join(delimiter)
153
+ end
154
+ end
@@ -0,0 +1,270 @@
1
+ require File.join(File.dirname(__FILE__), '../lib/resume')
2
+
3
+ describe Resume do
4
+ before(:each) do
5
+ @empty = EmptyResume
6
+ @resume = DummyResume
7
+ @alternate = AlternateDummyResume
8
+ end
9
+
10
+ it "should do the simplest thing possible" do
11
+ @resume.should_not be_nil
12
+ end
13
+
14
+ it "should have a name based on the class its included in" do
15
+ @resume.my_name.should == "Dummy Resume"
16
+ end
17
+
18
+ it "should even do middle names and more" do
19
+ @alternate.my_name.should == "Alternate Dummy Resume"
20
+ end
21
+
22
+ describe "schools" do
23
+ it "should have no schools if there are none" do
24
+ @empty.schools.should be_empty
25
+ end
26
+
27
+ it "should say its got no schools if there are none" do
28
+ @empty.has_schools?.should be_false
29
+ end
30
+
31
+ it "should include a school if there is one" do
32
+ @resume.schools.first[:name].should == "XYZU"
33
+ end
34
+
35
+ it "should say it has schools if it does" do
36
+ @resume.has_schools?.should be_true
37
+ end
38
+
39
+ it "should include year if supplied" do
40
+ @resume.schools.first[:graduated].should == "1999"
41
+ end
42
+
43
+ it "should include degree if supplied" do
44
+ @resume.schools.first[:degree].should == "PHD"
45
+ end
46
+
47
+ it "should include curriculum if supplied" do
48
+ @resume.schools.first[:curriculum].should == "Basket Weaving"
49
+ end
50
+
51
+ it "should have 1 school if said school is supplied" do
52
+ @resume.schools.size == 1
53
+ end
54
+
55
+ it "should have 2 schools if said schools are supplied" do
56
+ @alternate.schools.size == 2
57
+ end
58
+ end
59
+
60
+ describe "jobs" do
61
+ it "should have no jobs if there are none" do
62
+ @empty.jobs.should be_empty
63
+ end
64
+
65
+ it "should say it has not jobs if there are none" do
66
+ @empty.has_jobs?.should be_false
67
+ end
68
+
69
+ it "should include a job if there is one" do
70
+ @resume.jobs.first[:company].should == "Acme, Inc."
71
+ end
72
+
73
+ it "should say it has jobs if there are some" do
74
+ @resume.has_jobs?.should be_true
75
+ end
76
+
77
+ it "should include a description if there is one" do
78
+ @resume.jobs.first[:description].should == "bored out of skull"
79
+ end
80
+
81
+ it "should include a position if there is one" do
82
+ @resume.jobs.first[:position].should == "Monkey"
83
+ end
84
+
85
+ it "should include a tenure if there is one" do
86
+ @resume.jobs.first[:tenure].should == 2008
87
+ end
88
+ end
89
+
90
+ describe "applications" do
91
+ it "should have no applications if there are none" do
92
+ @empty.applications.should be_empty
93
+ end
94
+
95
+ it "should say it has not apps if there are none" do
96
+ @empty.has_applications?.should be_false
97
+ end
98
+
99
+ it "should have applications if there are some" do
100
+ @resume.applications.should == ["foo.com", "bar.net", "baz.org"]
101
+ end
102
+
103
+ it "should say it has apps if there are some" do
104
+ @resume.has_applications?.should be_true
105
+ end
106
+
107
+ it "should also add applications if there are multiples" do
108
+ @alternate.applications.should == ["biz.gov", "buzz.biz"]
109
+ end
110
+ end
111
+
112
+ describe "technologies" do
113
+ it "should have no technologies if there are none" do
114
+ @empty.technologies.should be_empty
115
+ end
116
+
117
+ it "should say it has no tech if there is none" do
118
+ @empty.has_technologies?.should be_false
119
+ end
120
+
121
+ it "should have technologies if there are some" do
122
+ @resume.technologies.should == ["countin", "readin", "spellin", "typin"]
123
+ end
124
+
125
+ it "should say it has tech if there is some" do
126
+ @resume.has_technologies?.should be_true
127
+ end
128
+
129
+
130
+ it "should also add technologies if there are multiples" do
131
+ @alternate.technologies.should == ["countin", "readin"]
132
+ end
133
+ end
134
+
135
+ describe "practices" do
136
+ it "should have no practices if there are none" do
137
+ @empty.practices.should be_empty
138
+ end
139
+
140
+ it "should say it has no practices if there is none" do
141
+ @empty.has_practices?.should be_false
142
+ end
143
+
144
+ it "should have practices if there are some" do
145
+ @resume.practices.should == ["law", "surgery", "juggling", "golf"]
146
+ end
147
+
148
+ it "should say it has practices if there are some" do
149
+ @resume.has_practices?.should be_true
150
+ end
151
+
152
+ it "should also add practices if there are multiples" do
153
+ @alternate.practices.should == ["law", "surgery"]
154
+ end
155
+ end
156
+
157
+ describe "contact" do
158
+ it "should include email" do
159
+ @resume.contact_info[:email].should == "foo@bar.com"
160
+ end
161
+
162
+ it "should say it has contact_info if there are some" do
163
+ @resume.has_contact_info?.should be_true
164
+ end
165
+
166
+ it "should include phone" do
167
+ @resume.contact_info[:phone].should == "800.444.3333"
168
+ end
169
+ end
170
+
171
+ describe "story" do
172
+ it "should include a story" do
173
+ @resume.story_text.should == "some story that this resume has and it does too"
174
+ end
175
+
176
+ it "should say there is a story" do
177
+ @resume.has_story?.should be_true
178
+ end
179
+
180
+ it "should not include a story if there isn't one" do
181
+ @empty.story_text.should be_empty
182
+ end
183
+
184
+ it "should not say there is a story" do
185
+ @empty.has_story?.should be_false
186
+ end
187
+ end
188
+
189
+ describe "pretty_print" do
190
+ before(:each) do
191
+ @print = ""
192
+ @resume.pretty_print(@print)
193
+ @alt_print = ""
194
+ @alternate.pretty_print(@alt_print)
195
+ end
196
+
197
+ it "should have a line" do
198
+ @resume.line.length.should == @resume.width
199
+ end
200
+
201
+ it "should use the name" do
202
+ @print.should match(/Dummy Resume/)
203
+ end
204
+
205
+ it "should use with a line" do
206
+ @print.should be_include(@resume.line)
207
+ end
208
+
209
+ it "should use the email" do
210
+ @print.should match(/foo@bar.com/)
211
+ end
212
+
213
+ it "should use the phone" do
214
+ @print.should match(/800.444.3333/)
215
+ end
216
+
217
+ it "should print schools out" do
218
+ @alt_print.should match(/Bachelor's/)
219
+ @alt_print.should match(/PHD/)
220
+ end
221
+
222
+ it "should print jobs" do
223
+ @print.should match(/Acme, Inc./)
224
+ @print.should match(/bored out of skull/)
225
+ @print.should match(/Monkey/)
226
+ @print.should match(/2008/)
227
+ end
228
+
229
+ it "should print websites" do
230
+ @print.should match(/foo.com/)
231
+ @print.should match(/bar.net/)
232
+ @print.should match(/baz.org/)
233
+ end
234
+
235
+ it "should print the story" do
236
+ @print.should match(/some story that this resume has and it does too/)
237
+ end
238
+ end
239
+ end
240
+
241
+ class EmptyResume
242
+ include Resume
243
+ end
244
+
245
+ class DummyResume
246
+ include Resume
247
+ contact :email => %w(foo bar com), :phone => %w(800 444 3333)
248
+ attended "XYZU", :in => "Basket Weaving", :with => "PHD", :graduated => "1999"
249
+ worked :at => "Acme, Inc.", :description => "bored out of skull", :position => "Monkey", :tenure => 2008
250
+ built %w(foo.com bar.net baz.org)
251
+ using %w(countin readin spellin typin)
252
+ practicing %w(law surgery juggling golf)
253
+ story %w(some story that this resume has and it does too)
254
+ end
255
+
256
+ class AlternateDummyResume
257
+ include Resume
258
+ attended "XYZU", :in => "Basket Weaving", :with => "Bachelor's", :graduated => "1908"
259
+ attended "XYZU", :in => "Basket Weaving", :with => "PHD", :graduated => "1999"
260
+ worked :at => "Acme, Inc.", :description => "bored out of skull", :position => "Monkey", :tenure => 2008
261
+ worked :at => "Backnecorp", :description => "bored out of back", :position => "Picker", :tenure => 2004
262
+
263
+ built "biz.gov"
264
+ built "buzz.biz"
265
+ using "countin"
266
+ using "readin"
267
+ practicing "law"
268
+ practicing "surgery"
269
+ end
270
+
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: resume
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2008-11-13 00:00:00 -08:00
8
+ summary: A Resume Gem
9
+ require_paths:
10
+ - lib
11
+ email: josh@kleinpeter.org
12
+ homepage: http://j05h.tumblr.com/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: resume
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Josh Kleinpeter
31
+ files:
32
+ - bin/resume
33
+ - lib/pdf_printer.rb
34
+ - lib/resume.rb
35
+ - README
36
+ test_files:
37
+ - spec/resume_spec.rb
38
+ rdoc_options: []
39
+
40
+ extra_rdoc_files:
41
+ - README
42
+ executables:
43
+ - resume
44
+ extensions: []
45
+
46
+ requirements: []
47
+
48
+ dependencies:
49
+ - !ruby/object:Gem::Dependency
50
+ name: prawn
51
+ version_requirement:
52
+ version_requirements: !ruby/object:Gem::Version::Requirement
53
+ requirements:
54
+ - - ">"
55
+ - !ruby/object:Gem::Version
56
+ version: 0.0.0
57
+ version: