Getting Started with Ruby, II: Strings and Things

This entry is part 2 of 6 in the series Getting Started with Ruby

Getting Started with Ruby

In the last part of this series we were introduced to the Ruby programming language and wrote our first program. We also used IRB to experiment and put our program on the web using Sinatra. In this post, we’re going to look at strings and their methods as well as using variables to store information.

String Theory

A string in Ruby is a collection of letters (or ‘characters’ to be more precise). A string literal can be created by writing a group of characters inside quotation marks:

"hello"

You can also use single quotation marks:

'hi there'

If you want to use quotation marks inside a string literal, you can just use the other type of quotation mark like so:

"It's done like this"

Or if your prefer, you can escape the quotation mark using the \ character, like so:

'Here\'s another way to do it'

In the last post, I mentioned that everything in Ruby is an object. Objects can perform actions called methods. There are a few ways of getting an object to perform a method, but the most common is the dot notation, which looks like this:

object.method

Let’s use irb to play around with some string objects and methods – open up a terminal console and start IRB using the following command:

$ irb

Now let’s have a go at calling the length on the string literal object “hello”:

> "hello".length
=> 5

This is the length method, and as you can see, it tells us how many characters are in the string.

Variables

Variables are very common in programming languages. They are a way of storing an object in memory for later use. In Ruby, we can assign a variable to an object very easily using the = operator, like in the example below:

name = "Darren"

The variable name now refers to the string literal object “Darren Jones”. This means I can call methods on the variable, rather than having to type in the string each time:

>  name.length
=> 6

Now we have my name stored as a variable, let’s try out a few more methods that can be used on string objects. We can write it backwards:

> name.reverse
=> "nerraD"

… write in capital letters:

> name.upcase
=> "DARREN"

…. or lower-case letters:

> name.downcase
=> "darren"

There are loads of other string methods. You can find out what they are by calling the methods method on a string (that’s right there’s a ‘method’ for finding out what an object’s methods are!)

> name.methods
=> [:<=>, :==, :===, :eql?, :hash, :casecmp, :+, :*, :%, :[], :[]=, :insert, :length, :size, :bytesize, :empty?, :=~, :match, :succ, :succ!, :next, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :getbyte, :setbyte, :byteslice, :to_i, :to_f, :to_s, :to_str, :inspect, :dump, :upcase, :downcase, :capitalize, :swapcase, :upcase!, :downcase!, :capitalize!, :swapcase!, :hex, :oct, :split, :lines, :bytes, :chars, :codepoints, :reverse, :reverse!, :concat, :<<, :prepend, :crypt, :intern, :to_sym, :ord, :include?, :start_with?, :end_with?, :scan, :ljust, :rjust, :center, :sub, :gsub, :chop, :chomp, :strip, :lstrip, :rstrip, :sub!, :gsub!, :chop!, :chomp!, :strip!, :lstrip!, :rstrip!, :tr, :tr_s, :delete, :squeeze, :count, :tr!, :tr_s!, :delete!, :squeeze!, :each_line, :each_byte, :each_char, :each_codepoint, :sum, :slice, :slice!, :partition, :rpartition, :encoding, :force_encoding, :b, :valid_encoding?, :ascii_only?, :unpack, :encode, :encode!, :to_r, :to_c, :>, :>=, :<, :<=, :between?, :nil?, :!~, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]

There are quite a few strange ones, but it should be obvious what some of them do, if not, you can find out by reading the documentation.

Bang! Methods

Some methods will not actually change the object itself. For example, let’s have a look at the reverse method. This, as you might guess, writes the string backwards, like so:

> name.reverse
 => "nerraD"

Now have a look at the object stored as the variable name:

> name
 => "Darren"

The object hasn’t changed. The reverse method returned a string that was the reverse name, but it didn’t actually alter name itself.

There is another String method called reverse! (it has an exclamation mark or ‘bang’ on the end). This is an example of a ‘bang method’ and, in Ruby, this means ‘be careful, this method could be dangerous’. In the case of reverse! it means that it will modify the string that calls the method, as you can see in the following example:

> name.reverse!
=> "nerraD"
name
=> "nerraD"

Now the string stored as name has been modified for good. Most string methods have a ‘bang equivalent’, for example there are upcase! and downcase! methods too.

Chaining Methods

You don’t have to apply each method one at a time. You can chain the methods together one after the other. For example, if I wanted to write your name backwards AND in capitals you could chain the reverse and upcase methods together like so:

> name = "Darren"
=> "Darren"
> name.reverse.upcase
=> "NERRAD"

The methods are applied in order from left to right (although in this case it didn’t matter, it may in others).

Interpolation

Interpolation is a neat way of inserting Ruby code into a string. This is done by placing the code inside #{ these symbols } inside a string like so:

"Welcome to my program, #{name}"
=> "Welcome to my program, Darren"
"Do you know that you're name backwards is #{name.reverse.downcase.capitalize}?"
=> "Do you know that you're name backwards is Nerrad?"

NOTE: The string MUST be a double-quoted string. Single quoted-strings do not perform interpolation.

Greeter Program

Now we’ve played around with some strings in IRB, it’s time to write an actual Ruby program. Create a file called ‘greeter.rb’ and enter the following code:

puts "Please enter your name:"
name = gets.chomp
puts "Hello #{name}! Did you know that you're name has #{name.length} letters in it and written backwards it is '#{name.reverse.downcase.capitalize}'?"

We saw the puts method in the last post. We’ve used it here on the first line to output the string “Please enter your name:” to the terminal. On the second line we introuduce a new method called gets. This will pause the program and wait for an input from the user (terminated by pressing the ENTER key). This will be stored in a variable called name. This will be a string and we apply a method called chomp to it. chomp removes the character created by pressing ENTER from the end of the string. We can then use string interpolation and some of the string methods that we have just learnt about to display information about the person’s name.

If you run the program by typing ruby greeter.rb into a terminal, you should see something similar to the following:

$ ruby greeter.rb 
Please enter your name:
Darren
Hello Darren! Did you know that you're name has 6 letters in it and written backwards it is 'Nerrad'?

Madlibs Program

Our next program is a simple implementation of the game Madlibs, where the user enters the names of some things and they are put together to make a (possibly) humorous phrase. Enter the following code into a file called ‘madlibs.rb':

puts "Please enter an animal:"
animal = gets.chomp
puts "Please enter an type of person:"
person = gets.chomp
puts "Please enter an object:"
object = gets.chomp
puts "Please enter an adjective:"
adjective = gets.chomp
puts "Please enter a verb:"
verb = gets.chomp
puts "The #{adjective} #{animal} started to #{verb} because the #{person} ran away with the #{object}"

This code uses multiple gets statements to grab lots of data from the user and set each piece of information as a different variable. String interpolation is then used to display the information entered in a sentence. If you try running it using the command ruby madlibs.rb, you should see something similar to the following:

$ ruby madlibs.rb 
Please enter an animal:
cow
Please enter an type of person:
prince
Please enter an object:
banana
Please enter an adjective:
fuzzy
Please enter a verb:
cry
The fuzzy cow started to cry because the prince ran away with the banana

Have some fun playing around with that one!

Online Greeter Program

Now let’s use Sinatra to create web versions of the two programs we’ve just created. Most of the code will be the same, but the way we get the input from the user is different on the web. There are two ways of getting data on the web – from the URL string or from forms. We’ll recreate the greeter program by grabbing the person’s name from the URL. Save the following code in a file called ‘web_greeter.rb':

require 'sinatra'

get '/:name' do
  name = params[:name]
  "Hello #{name}! Did you know that you're name has #{name.length} letters in it and written backwards it is '#{name.reverse.downcase.capitalize}'?"
end

Here we have another route handler like we used in the last post, but the string contains :name which is called a named parameter. These are special tokens in the URL that can have any value. The value that is entered in the URL is held in the params hash. This is a special container that holds any values entered by a user in the same way as a variable (we’ll learn more about hashes in a later post).

For example, if I entered the URL ‘http://localhost:4567/Darren’ into the browser, the value of params[:name] would be “Darren”. If I went to ‘http://localhost:4567/Daz’ into the browser, the value of params[:name] would be “Daz”.

The value in the square brackets after params has to match what was used in the named parameter in the route handler. This allows you to use as many named parameters as you like.

To try this out, type ruby web_greeter.rb into a terminal and then visit http://localhost:4567/Darren and you should see a message displayed in your browser similar to the one shown in the screenshot below. Try putting different names into the URL to check that it works.

Screenshot2

Web Madlibs

For the Madlibs web program we’re going to use an HTML form to enter the data. Enter the following code and save it as web_madlibs.rb:

require 'sinatra'

get '/madlibs' do
  erb :questions
end

post '/madlibs' do
  animal = params[:animal]
  person = params[:person]
  object = params[:object]
  adjective = params[:adjective]
  verb = params[:verb]
  "The #{adjective} #{animal} started to #{verb} because the #{person} ran away with the #{object}"
end

__END__

@@questions
<!doctype html>
<html>
  <header>
    <title>Madlibs</title>
  </header>
  <body>
    <form method="POST" action="/madlibs">
      <p>Animal:</p>
      <input name="animal">
      <p>Person:</p>
      <input name="person">
      <p>Object:</p>
      <input name="object">
      <p>Adjective:</p>
      <input name="adjective">
      <p>Verb:</p>
      <input name="verb">
      <input type="submit" value="Create Madlib">
    </form>
  </body>
</html>

This is our most complicated program that we’ve created so far, but it isn’t as bad as it looks if we break it down into chunks.

The first part is a very straight forward route handler. This states that if the user visits the route ‘/madlibs’ then we will use ERB to display a view called ‘questions’.

ERB stands for ‘Embedded Ruby’ and is a templating engine that is used to generate dynamic HTML. A view is a piece of HTML code that gets displayed by the browser. We are using inline views in this example, which means that you write them at the bottom of the file after the __END__ declaration. The name of the view starts with @@. Here we have created a view called ‘questions’ that is actually just a bit of HTML that displays a form with some input fields. The important part of the form are the two attributes method="POST" action="/madlibs". This tells Sinatra to use the HTTP POST verb to send the form to the route ‘/madlibs’.

We then use this information to create a route handler to deal with what happens when the form is submitted. Notice that the second route handler uses the verb ‘post’ instead of ‘get’ – this is because it only deals with routes that have been posted (like the one from our form).

Inside the block after the route handler, we then write the code that deals with the information submitted from the form. This is again stored in the params hash. Each input field contains a name attribute that tells Sinatra where to save the value entered in that field in the params hash.

Therefore, the value entered in the input field with the attribute name="animal" will be stored in params[:animal]. In the route handler we store each piece of information as a variable and then use the same bit of string interpolation as we did in the program we wrote earlier to display our Madlib.

To have a go at this, kill the server if it’s still running from before by holding down ‘Ctrl’ and pressing ‘C’. Then start the server running again by typing ruby web_madlibs.rb into a terminal. If you visit http://localhost:4567/madlibs in your browser, you should see a form that looks similar to the one in the screenshot below:

Screenshot3

Have fun filling in the form and creating some funny Madlibs!

That’s All Folks

In the next part of the series we’re going to get mathematical by looking at numbers and control logic. In the meantime, have a play around with what we’ve covered so far and be sure to leave any questions or comments below.

Getting Started with Ruby

<< Getting Started with RubyGetting Started with Ruby, III: Numbers and Logic >>

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Ossama

    Awesome !
    Starting to love the way Ruby works :D

  • Bill

    Nice tuts! Keep it up.