Stepping out on a Limb - some very ugly code

Hi all,

I've spent a few minutes this morning working on some code for that Resume
Builder that was suggested to me on this list a few weeks ago...

I have written some horribly ugly procedural code and wanted to get some
input as to how I can make it more Ruby like.

My code is exceedingly redundant. The only "woohoo!" I have about it, is
that I didn't have to look anything up in reference to write it.

Anyway, I'm stepping out on a limb here and putting out some stuff... I've
ran the code and it works and does what I want.. I just know that it's
horribly tedious.

:slight_smile:

Thanks!

(PS - Don't make fun of me too harshly :slight_smile: )

#ResumeBuilder.rb

puts("Welcome to ResumeBuilder v.1")
puts("Please enter your first name: ")
first_name = gets.chomp.capitalize!
puts("Please enter your last name: ")
last_name = gets.chomp.capitalize!
full_name = first_name + " " + last_name
puts("You have entered " + full_name + " as your name. Is this correct?
(yes/no)")
correct = gets.chomp
if correct.downcase == "yes": puts("Excellent, " + first_name + "!")
    else puts("Please enter your first name: ")
    first_name = gets.chomp.capitalize!
    puts("Please enter your last name: ")
    last_name = gets.chomp.capitalize!
    puts("You have entered " + full_name + "! Is this correct? (yes/no)")
    correct = gets.chomp
    if correct.downcase == "yes": puts("Great, let's get started, " +
first_name + "!")
    else puts("Please come back when you know your name.")
    end
end

puts("Please enter your street number: ")
street_number = gets.chomp!
puts("Please enter your street name: ")
street_name = gets.chomp.capitalize!
puts("Please enter your city name: ")
city_name = gets.chomp.capitalize!
puts("Please enter your state: ")
state_name = gets.chomp.upcase!
puts("Please enter your zip code: ")
zip_code = gets.chomp!
puts("You have told me that you live at:\n" + street_number + " " +
street_name +"\n" + city_name + ", " + state_name + " " + zip_code + "\nIs
this correct? (yes/no)")
correct = gets.chomp
if correct.downcase == "yes": puts("Great, let's continue!")
    else puts("Please enter your street number: ")
    street_number = gets.chomp!
    puts("Please enter your street name: ")
    street_name = gets.chomp.capitalize!
    puts("Please enter your city name: ")
    city_name = gets.chomp.capitalize!
    puts("Please enter your state: ")
    state_name = gets.chomp.upcase!
    puts("Please enter your zip code: ")
    zip_code = gets.chomp!
    puts("You have told me that you live at:\n" + street_number + " " +
street_name +"\n" + city_name + ", " + state_name + " " + zip_code + "\nIs
this correct? (yes/no)")
    if correct.downcase == "yes": puts("Great, let's continue!")
        else puts("Please come back when you know where you live.")
    end
end

···

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

Hi, thanks for writing. It sounds like you have a fairly good sense of code aesthetics already, which will help you out as you progress. Just don't be too hard on yourself; while you correctly recognize that there's room for improvement, your code isn't too bad, given what it does.

That said, I guess three things stand out at the moment -- two are a matter of Ruby style, the other isn't really Ruby-specific.

First, it's probably more readable to avoid the "if cond:" syntax, particularly with an else clause. For instance, try this:

  if correct.downcase == "yes"
      puts("Great, let's continue!")
  else
      puts("Please come back when you know where you live.")
  end

instead of this:

  if correct.downcase == "yes": puts("Great, let's continue!")
      else puts("Please come back when you know where you live.")
  end

The second thing is that it's often more readable to take advantage of Ruby's string interpolation. For instance, you can write this:

  puts("You have entered #{ full_name } as your name. Is this correct? (yes/no)")

instead of this:

  puts("You have entered " + full_name + " as your name. Is this correct? (yes/no)")

(admittedly, in this particular case, it's almost purely a question of taste -- there's not a huge readability advantage between the two; the first is just more "idiomatic")

The third thing is about looking for recurring patterns in the code; the presence of such patterns has a lot to do with "ugly" code. The best way to deal with them is to factor them out -- in very much the same sense that you could rewrite 3x + 2x^2 as x(3 + 2x).

For instance: the main recurring pattern is a puts, followed by a gets.chomp. We can pull that out into a separate function:

  def prompt(string)
      puts(string)
      gets.chomp
  end

And rewrite the prompts accordingly:

  puts("Welcome to ResumeBuilder v.1")
  first_name = prompt("Please enter your first name: ").capitalize!
  last_name = prompt("Please enter your last name: ").capitalize!
  full_name = "#{ first_name } #{ last_name }"

(etc.)

At this point, another pattern becomes apparent: asking for a yes/no answer and checking whether it is equal to "yes". We can use the "prompt" function we've already built as part of another one just for yes/no answers:

  def boolean_prompt(string)
      prompt("#{ string } (yes/no)").downcase == "yes"
  end

And then you can rewrite the yes/no questions like this:

  correct = boolean_prompt("You have entered #{ full_name } as your name. Is this correct?")
  if correct
      puts("Great, let's get started, #{ first_name }!")
  else
      puts("Please come back when you know your name.")
      exit 1
  end

[ note that I've added an "exit 1" to leave the program in the case where the name was wrong, which seems to have been your intent? ]

Anyway, those are the major items which come to mind at the moment. We could probably continue refactoring the code like this a little bit further (for instance, a "prompt" function just for capitalized input), but I think that'd be passsing a point of diminishing returns -- your program is already a pretty concise expression of what it does. Also, because of that, don't worry too much that your program isn't using classes or other "special" Ruby features just yet -- as you add more functionality to your program, there will be plenty of opportunities to refactor code to use them.

-mental

···

On Thu, 1 Mar 2007 02:56:25 +0900, Samantha <rubygeekgirl@gmail.com> wrote:

I have written some horribly ugly procedural code and wanted to get some
input as to how I can make it more Ruby like.

Samantha wrote:

My code is exceedingly redundant. The only "woohoo!" I have about it, is
that I didn't have to look anything up in reference to write it.

Well, I'm new to ruby too, but the most obvious things I would do is loop the gets so that you don't write everything twice, and make a method to handle the gets so that you don't write that 10 times. As far as making it more "rubyish", I'm sure I would mess that up, but I guess, with that in mind, I would at least put it in a class, and I personally like using string interpolation, it's more readable for me.

Raj

#ResumeBuilder.rb

class ResumeBuilder
  def initialize
    puts("Welcome to ResumeBuilder v.1")
    correct = ""
    until correct.downcase == "yes"
      @first_name = prompt_and_get("first name").chomp.capitalize
      @last_name = prompt_and_get("last name").chomp.capitalize
      @full_name = "#{@first_name} #{@last_name}"
      puts("You have entered #{@full_name} as your name.
Is this correct? (yes/no)")
      correct = gets.chomp
    end
    correct = ""
    until correct.downcase == "yes"
      @street_number = prompt_and_get("street number").chomp
      @street_name = prompt_and_get("street name").chomp.capitalize
      @city_name = prompt_and_get("city name").chomp.capitalize
      @state_name = prompt_and_get("state").chomp.upcase
      @zip_code = prompt_and_get("zip code").chomp
      puts "You have told me that you live at:
#{@street_number} #{@street_name}
#{@city_name}, #{@state_name} #{@zip_code}
Is this correct? (yes/no)"
      correct = gets.chomp
    end
  end

  def prompt_and_get(string)
    puts "Please enter your #{string}: "
    gets
  end
end

ResumeBuilder.new

How about something like this instead?

data=Hash.new
["street number","street name","city name","state","zip code"].each do |i|
  puts("Please enter your #{i}: ")
  data[i]=gets.chomp
end

HTH,
Sebastian

···

Am Mittwoch, 28. Februar 2007 18:56:25 schrieb Samantha:

puts("Please enter your street number: ")
street_number = gets.chomp!
puts("Please enter your street name: ")
street_name = gets.chomp.capitalize!
puts("Please enter your city name: ")
city_name = gets.chomp.capitalize!
puts("Please enter your state: ")
state_name = gets.chomp.upcase!
puts("Please enter your zip code: ")
zip_code = gets.chomp!

--
NP: Anathema - Suicide Veil
Ist so, weil ist so
Bleibt so, weil war so

> I have written some horribly ugly procedural code and wanted to get some
> input as to how I can make it more Ruby like.

Hi, thanks for writing. It sounds like you have a fairly good sense of
code aesthetics already, which will help you out as you progress. Just
don't be too hard on yourself; while you correctly recognize that there's
room for improvement, your code isn't too bad, given what it does.

That said, I guess three things stand out at the moment -- two are a
matter of Ruby style, the other isn't really Ruby-specific.

First, it's probably more readable to avoid the "if cond:" syntax,
particularly with an else clause. For instance, try this:

  if correct.downcase == "yes"
      puts("Great, let's continue!")
  else
      puts("Please come back when you know where you live.")
  end

instead of this:

  if correct.downcase == "yes": puts("Great, let's continue!")
      else puts("Please come back when you know where you live.")
  end

That's funny! :slight_smile: I Say that because I normally write my if/else statements
like that, but decided to try it with the : syntax

The second thing is that it's often more readable to take advantage of

Ruby's string interpolation. For instance, you can write this:

  puts("You have entered #{ full_name } as your name. Is this correct?
(yes/no)")

instead of this:

  puts("You have entered " + full_name + " as your name. Is this correct?
(yes/no)")

(admittedly, in this particular case, it's almost purely a question of
taste -- there's not a huge readability advantage between the two; the first
is just more "idiomatic")

*nod* That makes sense, especially because I ended up running into syntax
errors because it's easy to miss putting in a + sign.

The third thing is about looking for recurring patterns in the code; the

presence of such patterns has a lot to do with "ugly" code. The best way to
deal with them is to factor them out -- in very much the same sense that you
could rewrite 3x + 2x^2 as x(3 + 2x).

And, that's exactly where I knew I could improve and where I was having
problems minimizing the code.

For instance: the main recurring pattern is a puts, followed by a
gets.chomp. We

can pull that out into a separate function:

  def prompt(string)
      puts(string)
      gets.chomp
  end

And rewrite the prompts accordingly:

Ohhhh. I like it.

  puts("Welcome to ResumeBuilder v.1")

  first_name = prompt("Please enter your first name: ").capitalize!
  last_name = prompt("Please enter your last name: ").capitalize!
  full_name = "#{ first_name } #{ last_name }"

(etc.)

At this point, another pattern becomes apparent: asking for a yes/no
answer and checking whether it is equal to "yes". We can use the "prompt"
function we've already built as part of another one just for yes/no answers:

  def boolean_prompt(string)
      prompt("#{ string } (yes/no)").downcase == "yes"
  end

And then you can rewrite the yes/no questions like this:

  correct = boolean_prompt("You have entered #{ full_name } as your
name. Is this correct?")
  if correct
      puts("Great, let's get started, #{ first_name }!")
  else
      puts("Please come back when you know your name.")
      exit 1
  end

[ note that I've added an "exit 1" to leave the program in the case where
the name was wrong, which seems to have been your intent? ]

Yeah, that was my intent, I just wasn't 100% sure how to get out of there.
I gave the user two chances to properly input their answer, and if they
couldn't get their name right they were SOL.

Anyway, those are the major items which come to mind at the moment. We

could probably continue refactoring the code like this a little bit further
(for instance, a "prompt" function just for capitalized input), but I think
that'd be passsing a point of diminishing returns -- your program is already
a pretty concise expression of what it does. Also, because of that, don't
worry too much that your program isn't using classes or other "special" Ruby
features just yet -- as you add more functionality to your program, there
will be plenty of opportunities to refactor code to use them.

Thanks! So I guess I did get something out of my Programming Logic & Design
class last semester. I really appreciate your response. It shed light on
what I wanted to do. :slight_smile:

-mental

···

On 2/28/07, MenTaLguY <mental@rydia.net> wrote:

On Thu, 1 Mar 2007 02:56:25 +0900, Samantha <rubygeekgirl@gmail.com> > wrote:

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

Well, I'm new to ruby too, but the most obvious things I would do is

loop the gets so that you don't write everything twice, and make a
method to handle the gets so that you don't write that 10 times. As far
as making it more "rubyish", I'm sure I would mess that up, but I guess,
with that in mind, I would at least put it in a class, and I personally
like using string interpolation, it's more readable for me.

Raj

#ResumeBuilder.rb

class ResumeBuilder
  def initialize
    puts("Welcome to ResumeBuilder v.1")
    correct = ""
    until correct.downcase == "yes"
      @first_name = prompt_and_get("first name").chomp.capitalize
      @last_name = prompt_and_get("last name").chomp.capitalize
      @full_name = "#{@first_name} #{@last_name}"
      puts("You have entered #{@full_name} as your name.
Is this correct? (yes/no)")
      correct = gets.chomp
    end
    correct = ""
    until correct.downcase == "yes"
      @street_number = prompt_and_get("street number").chomp
      @street_name = prompt_and_get("street name").chomp.capitalize
      @city_name = prompt_and_get("city name").chomp.capitalize
      @state_name = prompt_and_get("state").chomp.upcase
      @zip_code = prompt_and_get("zip code").chomp
      puts "You have told me that you live at:
#{@street_number} #{@street_name}
#{@city_name}, #{@state_name} #{@zip_code}
Is this correct? (yes/no)"
      correct = gets.chomp
    end
  end

  def prompt_and_get(string)
    puts "Please enter your #{string}: "
    gets
  end
end

ResumeBuilder.new

Thanks for the answer, Raj. I think that this is going to be a good way for
me to learn and improve!

···

On 2/28/07, Raj Sahae <rajsahae@gmail.com> wrote:

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

> puts("Please enter your street number: ")
> street_number = gets.chomp!
> puts("Please enter your street name: ")
> street_name = gets.chomp.capitalize!
> puts("Please enter your city name: ")
> city_name = gets.chomp.capitalize!
> puts("Please enter your state: ")
> state_name = gets.chomp.upcase!
> puts("Please enter your zip code: ")
> zip_code = gets.chomp!

How about something like this instead?

data=Hash.new
["street number","street name","city name","state","zip code"].each do |i|
  puts("Please enter your #{i}: ")
  data[i]=gets.chomp
end

That's an angle I hadn't even thought of! Thank you!

HTH,

···

On 2/28/07, Sebastian Hungerecker <sepp2k@googlemail.com> wrote:

Am Mittwoch, 28. Februar 2007 18:56:25 schrieb Samantha:
Sebastian
--
NP: Anathema - Suicide Veil
Ist so, weil ist so
Bleibt so, weil war so

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

Samantha wrote:

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

thanx sammantha for asking....i've printed these suggestions and will
put into use myself....dave

···

--
Posted via http://www.ruby-forum.com/\.

Okay ... I wrote that up and it inputs things, but I have a few questions...

1) After getting the information from the user, I want to be able to output
the information on the screen and get a confirmation. I'm assuming that I
do that with:

contact_info.each do |i|
puts i
end

Yes? So... 1) How do I get this to be 'pretty' or formatted nicely like the
original code, and 2) How do I get the state abbreviation as all upcase?

···

On 2/28/07, Samantha <rubygeekgirl@gmail.com> wrote:

On 2/28/07, Sebastian Hungerecker <sepp2k@googlemail.com> wrote:
>
> How about something like this instead?
>
> data=Hash.new
> ["street number","street name","city name","state","zip code"].each do
> >i>
> puts("Please enter your #{i}: ")
> data[i]=gets.chomp
> end

HTH,
> Sebastian
> --
> NP: Anathema - Suicide Veil
> Ist so, weil ist so
> Bleibt so, weil war so

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

Just use contact_info["x"] to access information x (e.g. contact_info["street
name"] to access the street name), assuming contact_info is what you called
the hash (although I would recommend just calling it info, because that's less
to type :wink: )

···

Am Mittwoch, 28. Februar 2007 20:52:44 schrieb Samantha:

On 2/28/07, Samantha <rubygeekgirl@gmail.com> wrote:
> On 2/28/07, Sebastian Hungerecker <sepp2k@googlemail.com> wrote:

> > data=Hash.new
> > ["street number","street name","city name","state","zip code"].each do
> > >i>
> > puts("Please enter your #{i}: ")
> > data[i]=gets.chomp
> > end

Okay ... I wrote that up and it inputs things, but I have a few
questions...

1) After getting the information from the user, I want to be able to output
the information on the screen and get a confirmation. I'm assuming that I
do that with:

contact_info.each do |i|
puts i
end

Yes? So... 1) How do I get this to be 'pretty' or formatted nicely like
the original code, and 2) How do I get the state abbreviation as all
upcase?

--
Ist so, weil ist so
Bleibt so, weil war so

Well, there's always more than one way to do anything,
but here's one late night hack :slight_smile:

#!/usr/bin/env ruby

class ResumeBuilder
  def initialize
    @data = {}
    @fields = ['First Name',
               'Last Name' ,
               'Address' ,
               'City' ,
               'State' ,
               'Zip' ]
  end

  def prompt
    @fields.each do |field|
      val = @data[field]
      print "Please enter your #{field}#{(' (' + val + ')') if val}:"
      val = gets.chomp
      @data[field] = val if val != ''
    end
  end

  def confirm?
    puts "You entered:"
    @fields.each do |field|
      puts field + ': ' + @data[field].to_s
    end
    print "Is this correct? (Y/n)"
    gets.chomp == 'Y'
  end
end

resume = ResumeBuilder.new
resume.prompt
resume.prompt until resume.confirm?

I didn't bother with the formatting, but you get the idea.
You might also look at using a Struct.

-Brian

···

--
Posted via http://www.ruby-forum.com/.

Gotcha, so... i'd type

puts contact_info["state_name"].upcase

to access and change the state abbreviation to all uppercase, then, yes? :slight_smile:

Thanks again for being so helpful!

Being that I wrote out the 'procedural' type code before, I am going to use
all these tips and rewrite the same program piece and add on to it, using
different techniques...

:slight_smile:

···

On 2/28/07, Sebastian Hungerecker <sepp2k@googlemail.com> wrote:

Am Mittwoch, 28. Februar 2007 20:52:44 schrieb Samantha:
> On 2/28/07, Samantha <rubygeekgirl@gmail.com> wrote:
> > On 2/28/07, Sebastian Hungerecker <sepp2k@googlemail.com> wrote:

> > > data=Hash.new
> > > ["street number","street name","city name","state","zip code"].each
do
> > > >i>
> > > puts("Please enter your #{i}: ")
> > > data[i]=gets.chomp
> > > end

> Okay ... I wrote that up and it inputs things, but I have a few
> questions...
>
> 1) After getting the information from the user, I want to be able to
output
> the information on the screen and get a confirmation. I'm assuming that
I
> do that with:
>
> contact_info.each do |i|
> puts i
> end
>
> Yes? So... 1) How do I get this to be 'pretty' or formatted nicely like
> the original code, and 2) How do I get the state abbreviation as all
> upcase?

Just use contact_info["x"] to access information x (e.g.
contact_info["street
name"] to access the street name), assuming contact_info is what you
called
the hash (although I would recommend just calling it info, because that's
less
to type :wink: )

--

Ist so, weil ist so
Bleibt so, weil war so

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

Comments inline so I can make sure I really "understand" what's being done
here...

Well, there's always more than one way to do anything,
but here's one late night hack :slight_smile:

#!/usr/bin/env ruby

class ResumeBuilder
  def initialize
    @data = {}
    @fields = ['First Name',
               'Last Name' ,
               'Address' ,
               'City' ,
               'State' ,
               'Zip' ]
  end

--- I'm assuming that here you are defining the class that is
ResumeBuilder... you've got the @data and @fields that are instance
variables, right? @data is an empty hash and @fields is an array...

  def prompt

    @fields.each do |field|
      val = @data[field]
      print "Please enter your #{field}#{(' (' + val + ')') if val}:"
      val = gets.chomp
      @data[field] = val if val != ''
    end
  end

--- Here you're defining the prompt method... and inserting each item from
the @field array into the hash... then you're putting the answer that is
given into the value for the item in the hash? (wow, that's a hard one to
articulate when ya don't know all the lingo" and then you are ending it if
val doesn't have anything?

  def confirm?

    puts "You entered:"
    @fields.each do |field|
      puts field + ': ' + @data[field].to_s
    end
    print "Is this correct? (Y/n)"
    gets.chomp == 'Y'
  end
end

--- here is the confirmation section... You're telling the user what they
entered for each value by iterating through the hash/array?

resume = ResumeBuilder.new

resume.prompt
resume.prompt until resume.confirm?

and here you are defining that the variable resume is a new instance of the
Class ResumeBuilder... I'm kind of lost on the last line...

I didn't bother with the formatting, but you get the idea.

You might also look at using a Struct.

Will do! Thanks for the input! I'm finding that this is a really good way
to learn.

-Brian

···

On 3/1/07, Brian Burns <wizard.rb@gmail.com> wrote:

--
Posted via http://www.ruby-forum.com/\.

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

After taking several suggestions, I've come up with 91 lines of code
(including blank lines because I like organizing things).

I have a few issues in certain areas of the code...

I'll post all 91 lines (including lines intentionally left blank), and
explain what I'm having go wrong... I'm just not getting it, but maybe I
don't quite understand certain things... (probably, not maybe :wink: (And
please excuse the rude prompts - I'm not really this rude, nor would I write
such a rude program for deployment into the world.)

#ResumeBuilder.rb

#This is the section that defines a prompt.
def prompt(string)
  puts(string)
  gets.chomp
end

#This section defines a prompt that requires a yes or no answer.
def boolean_prompt(string)
  prompt("#{string} (yes/no)").downcase == "yes"
end

#Main program logic for User Identity
puts("Welcome to Resume Builder v.1")

first_name = prompt("Please enter your first name: ").capitalize!
last_name = prompt("Please enter your last name: ").capitalize!

#This verifies that the user is who they said they were.
correct = boolean_prompt("So, your name is #{first_name} #{last_name}?")
if correct
  puts("Great! Let's get started, #{first_name}!")
else
  puts("Please come back when you know who you are.")
  exit 1
end

------------When I get to this point, if I typed in the answers to the
prompts with the first letter capitalized (ie Samantha for the first name),
when the program verifies what I typed whatever values it is verifying, as
blank...

#now we get the address information of the user
street_number = prompt("Please enter your street number: ")
street_name = prompt("Please enter your street name: ").capitalize!
city_name = prompt("Please enter your city name: ").capitalize!
state_name = prompt("Please enter the state you live in: ").upcase!
zip_code = prompt("Please enter your zip code: ")
phone_number = prompt("Please enter your phone number in the following
format: (999) 999-9999: ")
email_address = prompt("Please enter your email address in the follwoing
format: name@domain.com: ")

correct = boolean_prompt("Your address is: \n#{street_number}
#{street_name}\n#{city_name}, #{state_name} #{zip_code}\nYour phone number
is #{phone_number} and your email address is #{email_address}.\nIs this
correct? ")
if correct
  puts("Great! Let's continue!")
else
  puts("Please come back when you know where you live.")
  exit 1
end

#this section gets the objective of the candidate.
objective = prompt("Please enter a short description of your career
objective, making sure you use proper rules of capitalization.")
correct = boolean_prompt("You said your career objective is,
\"#{objective}\" Is this correct?" )
if correct
  puts("Good, now moving on, let's get a little information about your
skills.")
else
  puts("Please come back when you have some goals.")
  exit 1
end

#this section gathers the skillset of the user and puts them into an array.
puts("Please enter your technical skills - one per line. When you are
complete, please leave a blank line and hit enter.")
tech_skills = []
while (answer = gets.chomp)
  break if answer.empty?
  tech_skills.push(answer)
end

puts("Your skills are as follows:\n")
tech_skills.each do |skill|
puts skill
end

correct = boolean_prompt("Is this correct?")
if correct
  puts("Great, let's move onto your experience.")
else
  puts("Please come back when you know what you can do with yourself. :)")
  exit 1
end

#This section gathers experience from the user.
company1 = Hash.new
["Company Name","Company City","Company State","Start Date","End
Date","Position Held","Job Duties"].each do |input|
  puts("Please enter your #{input}: ")
  company1 = gets.chomp
end

correct = boolean_prompt("You worked at " + company1["Company Name"] + " as
a " + company1["Position Held"] + " from " + company1["Start Date"] + "
until " + company1["End Date"] + " and your job description was as follows:
\n" + company1["Job Duties"] + "\n" + company1["Company Name"] + " was
located in " + company1["Company City"] + ", " + company1["Company State"] +
"Is this correct? ")
if correct
  puts("Great, let's move on!")
else
  puts("Please come back when you have some experience to add to your
resume. In other words, GET A JOB! :)")
  exit 1
end

------------------The above section of code, from the hash section down...
gives an error... This is the output...

Is this correct? (yes/no)
yes
Great, let's move onto your experience.
Please enter your Company Name:
asdf
Please enter your Company City:
asdf
Please enter your Company State:
asdf
Please enter your Start Date:
April 2005
Please enter your End Date:
January 2007
Please enter your Position Held:
blah
Please enter your Job Duties:
blah
ResumeBuilder.rb:85:in `+': can't convert nil into String (TypeError)
        from ResumeBuilder.rb:85
/projects/dev/ResumeBuilder $

Line 85 begins with: correct = boolean_prompt("You worked at " + comp...

I'm really at a loss here. I thought that each company would fit nicely
into a Hash value... I've been banging my head against the wall for a while
now on this one.

···

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

Hi --

After taking several suggestions, I've come up with 91 lines of code
(including blank lines because I like organizing things).

I have a few issues in certain areas of the code...

I'll post all 91 lines (including lines intentionally left blank), and
explain what I'm having go wrong... I'm just not getting it, but maybe I
don't quite understand certain things... (probably, not maybe :wink: (And
please excuse the rude prompts - I'm not really this rude, nor would I write
such a rude program for deployment into the world.)

#ResumeBuilder.rb

#This is the section that defines a prompt.
def prompt(string)
puts(string)
gets.chomp
end

#This section defines a prompt that requires a yes or no answer.
def boolean_prompt(string)
prompt("#{string} (yes/no)").downcase == "yes"
end

#Main program logic for User Identity
puts("Welcome to Resume Builder v.1")

first_name = prompt("Please enter your first name: ").capitalize!
last_name = prompt("Please enter your last name: ").capitalize!

#This verifies that the user is who they said they were.
correct = boolean_prompt("So, your name is #{first_name} #{last_name}?")
if correct
puts("Great! Let's get started, #{first_name}!")
else
puts("Please come back when you know who you are.")
exit 1
end

------------When I get to this point, if I typed in the answers to the
prompts with the first letter capitalized (ie Samantha for the first name),
when the program verifies what I typed whatever values it is verifying, as
blank...

That's because capitalize!, like a lot of bang methods, returns nil if
no change has occurred in the receiver. So David.capitalize! is nil.

puts("Your skills are as follows:\n")
tech_skills.each do |skill|
puts skill
end

It's much easier than that:

   puts tech_skills

:slight_smile:

#This section gathers experience from the user.
company1 = Hash.new
["Company Name","Company City","Company State","Start Date","End
Date","Position Held","Job Duties"].each do |input|
puts("Please enter your #{input}: ")
company1 = gets.chomp

That's wrong; it should be:

   company1[input] = gets.chomp

since you want to set the relevant hash key. Also, make sure that
there's no newline between "End" and "Date", as that will cause
company1["End Date"] to be nil (as opposed to company1["End \nDate"]).

correct = boolean_prompt("You worked at " + company1["Company Name"] + " as
a " + company1["Position Held"] + " from " + company1["Start Date"] + "
until " + company1["End Date"] + " and your job description was as follows:
\n" + company1["Job Duties"] + "\n" + company1["Company Name"] + " was
located in " + company1["Company City"] + ", " + company1["Company State"] +
"Is this correct? ")

Consider a here-document:

prompt = <<EOM
You worked at #{company1["Company Name"]} as a ... (etc.)
EOM

It will look more like the eventual output.

David

···

On Thu, 1 Mar 2007, Samantha wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Samantha;

Cool script. I like the prompts :wink:

One cool thing about ruby is that if you put key/value pairs at the
end of a method call they all get mashed together into a hash. You
can use that to help with readability. For example, many times in the
code you check a boolean condition and then write out a message. You
could try something like this:

    def verify_info(ok, hash)
      if ok
        puts hash[:next]
      else
        puts hash[:fail]
        exit 1
      end
    end

Now the messages can be passed in like so:

    verify_info correct,
      :next => "Good, now moving on, let's get a little information
about your skills.",
      :fail => "Please come back when you have some goals."

Or even get rid of the "correct" variable:

    verify_info boolean_prompt("Is this correct?"),
      :next => "Great, let's move onto your experience.",
      :fail => "Please come back when you know what you can do with
yourself. :)"

In this case it doesn't afford you too much, but it does get rid of
the repeated pattern. Say you wanted to change the exit code. Now
you'd only need to edit it in one place.

···

On 2/28/07, Samantha <rubygeekgirl@gmail.com> wrote:

After taking several suggestions, I've come up with 91 lines of code
(including blank lines because I like organizing things).

I'll post all 91 lines (including lines intentionally left blank), and
explain what I'm having go wrong... I'm just not getting it, but maybe I
don't quite understand certain things... (probably, not maybe :wink: (And
please excuse the rude prompts - I'm not really this rude, nor would I write
such a rude program for deployment into the world.)

--
Lou.

Hi --

>
> ------------When I get to this point, if I typed in the answers to the
> prompts with the first letter capitalized (ie Samantha for the first
name),
> when the program verifies what I typed whatever values it is verifying,
as
> blank...

That's because capitalize!, like a lot of bang methods, returns nil if
no change has occurred in the receiver. So David.capitalize! is nil.

Ahhh, that makes sense. I tried it both ways, capitalizing and without
capitalizing, and noticed that it had that behavior. I don't think I want
to redefine the bang method (scary scary scary). But, what can I do to fix
this?

puts("Your skills are as follows:\n")
> tech_skills.each do |skill|
> puts skill
> end

It's much easier than that:

   puts tech_skills

:slight_smile:

*nod + laugh* I've done that in prior little things I've done - Donno why I
didn't do that this time.

#This section gathers experience from the user.
> company1 = Hash.new
> ["Company Name","Company City","Company State","Start Date","End
> Date","Position Held","Job Duties"].each do |input|
> puts("Please enter your #{input}: ")
> company1 = gets.chomp

That's wrong; it should be:

   company1[input] = gets.chomp

since you want to set the relevant hash key. Also, make sure that
there's no newline between "End" and "Date", as that will cause
company1["End Date"] to be nil (as opposed to company1["End \nDate"]).

> correct = boolean_prompt("You worked at " + company1["Company Name"] + "
as
> a " + company1["Position Held"] + " from " + company1["Start Date"] + "
> until " + company1["End Date"] + " and your job description was as
follows:
> \n" + company1["Job Duties"] + "\n" + company1["Company Name"] + " was
> located in " + company1["Company City"] + ", " + company1["Company
State"] +
> "Is this correct? ")

Consider a here-document:

prompt = <<EOM
You worked at #{company1["Company Name"]} as a ...
(etc.)
EOM

It will look more like the eventual output.

Thanks, David. I'll definitely need to digest all of that and try using it
in different ways. What I've been trying to do, is if someone gives me a
suggestion, not only do I try and use it in what I'm working on, but I'm
also trying to find another way to use it, that way it sinks in a little
better.

Thanks for the response, I really truly appreciate it.

David

···

On 2/28/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

If you keep doing a lot of this, you might want to look into the HighLine library. It gives you the tools to validate and convert input as well as issue error messages on certain conditions:

http://highline.rubyforge.org/

James Edward Gray II

···

On Mar 1, 2007, at 7:02 AM, Louis J Scoras wrote:

You could try something like this:

   def verify_info(ok, hash)
     if ok
       puts hash[:next]
     else
       puts hash[:fail]
       exit 1
     end
   end

> After taking several suggestions, I've come up with 91 lines of code
> (including blank lines because I like organizing things).

> I'll post all 91 lines (including lines intentionally left blank), and
> explain what I'm having go wrong... I'm just not getting it, but maybe I
> don't quite understand certain things... (probably, not maybe :wink: (And
> please excuse the rude prompts - I'm not really this rude, nor would I
write
> such a rude program for deployment into the world.)

Samantha;

Cool script. I like the prompts :wink:

I didn't write the prompt formula on my own, but I did write the sarcasm. :slight_smile:

One cool thing about ruby is that if you put key/value pairs at the

···

On 3/1/07, Louis J Scoras <louis.j.scoras@gmail.com> wrote:

On 2/28/07, Samantha <rubygeekgirl@gmail.com> wrote:
end of a method call they all get mashed together into a hash. You
can use that to help with readability. For example, many times in the
code you check a boolean condition and then write out a message. You
could try something like this:

    def verify_info(ok, hash)
      if ok
        puts hash[:next]
      else
        puts hash[:fail]
        exit 1
      end
    end

Now the messages can be passed in like so:

    verify_info correct,
      :next => "Good, now moving on, let's get a little information
about your skills.",
      :fail => "Please come back when you have some goals."

Or even get rid of the "correct" variable:

    verify_info boolean_prompt("Is this correct?"),
      :next => "Great, let's move onto your experience.",
      :fail => "Please come back when you know what you can do with
yourself. :)"

In this case it doesn't afford you too much, but it does get rid of
the repeated pattern. Say you wanted to change the exit code. Now
you'd only need to edit it in one place.

--

Lou.

So, what you're doing here is basically iterating through the hash and if
it gets an ok, it goes to the next value to confirm, and otherwise, it
fails?

--
Samantha

http://www.babygeek.org/

"Beware when the great God lets loose a thinker on this planet. Then all
things are at risk."
  --Ralph Waldo Emerson

Hi --

···

On Thu, 1 Mar 2007, Samantha wrote:

On 2/28/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

Hi --

>
> ------------When I get to this point, if I typed in the answers to the
> prompts with the first letter capitalized (ie Samantha for the first
name),
> when the program verifies what I typed whatever values it is verifying,
as
> blank...

That's because capitalize!, like a lot of bang methods, returns nil if
no change has occurred in the receiver. So David.capitalize! is nil.

Ahhh, that makes sense. I tried it both ways, capitalizing and without
capitalizing, and noticed that it had that behavior. I don't think I want
to redefine the bang method (scary scary scary). But, what can I do to fix
this?

Lose the !. Just issue a new string with capitalize. There's no
serious performance or memory issue here (unless someone has a name
the size of "War and Peace" :slight_smile:

David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)