You are previewing Learning Ruby.

Learning Ruby

Cover of Learning Ruby by Michael Fitzgerald Published by O'Reilly Media, Inc.
  1. Learning Ruby
    1. SPECIAL OFFER: Upgrade this ebook with O’Reilly
    2. A Note Regarding Supplemental Files
    3. Preface
      1. Who Should Read This Book?
      2. How This Book Works
      3. About the Examples
      4. How This Book Is Organized
      5. Conventions Used in This Book
      6. Comments and Questions
      7. Safari® Enabled
      8. Acknowledgments
    4. 1. Ruby Basics
      1. Hello, Matz
      2. Interactive Ruby
      3. Resources
      4. Installing Ruby
      5. Permission Denied
      6. Associating File Types on Windows
      7. Review Questions
    5. 2. A Quick Tour of Ruby
      1. Ruby Is Object-Oriented
      2. Ruby's Reserved Words
      4. Variables
      5. Strings
      6. Numbers and Operators
      7. Conditional Statements
      8. Arrays and Hashes
      9. Methods
      10. Blocks
      11. Symbols
      12. Exception Handling
      13. Ruby Documentation
      14. Review Questions
    6. 3. Conditional Love
      1. The if Statement
      2. The case Statement
      3. The while Loop
      4. The loop Method
      5. The for loop
      6. Execution Before or After a Program
      7. Review Questions
    7. 4. Strings
      1. Creating Strings
      2. Concatenating Strings
      3. Accessing Strings
      4. Comparing Strings
      5. Manipulating Strings
      6. Case Conversion
      7. Managing Whitespace, etc.
      8. Incrementing Strings
      9. Converting Strings
      10. Regular Expressions
      11. 1.9 and Beyond
      12. Review Questions
    8. 5. Math
      1. Class Hierarchy and Included Modules
      2. Converting Numbers
      3. Basic Math Operations
      4. Ranges
      5. Inquiring About Numbers
      6. More Math Methods
      7. Math Functions
      8. Rational Numbers
      9. Prime Numbers
      10. Review Questions
    9. 6. Arrays
      1. Creating Arrays
      2. Accessing Elements
      3. Concatenation
      4. Set Operations
      5. Unique Elements
      6. Blow Your Stack
      7. Comparing Arrays
      8. Changing Elements
      9. Deleting Elements
      10. Arrays and Blocks
      11. Sorting Things and About Face
      12. Multidimensional Arrays
      13. 1.9 and Beyond
      14. Other Array Methods
      15. Review Questions
    10. 7. Hashes
      1. Creating Hashes
      2. Accessing Hashes
      3. Iterating over Hashes
      4. Changing Hashes
      5. Converting Hashes to Other Classes
      6. 1.9 and Beyond
      7. Other Hash Methods
      8. Review Questions
    11. 8. Working with Files
      1. Directories
      2. Creating a New File
      3. Opening an Existing File
      4. Deleting and Renaming Files
      5. File Inquiries
      6. Changing File Modes and Owner
      7. The IO Class
      8. Review Questions
    12. 9. Classes
      1. Defining the Class
      2. Instance Variables
      3. Accessors
      4. Class Variables
      5. Class Methods
      6. Inheritance
      7. Modules
      8. public, private, or protected
      9. Review Questions
    13. 10. More Fun with Ruby
      1. Formatting Output with sprintf
      2. Processing XML
      3. Date and Time
      4. Reflection
      5. Using Tk
      6. Metaprogramming
      7. RubyGems
      8. Exception Handling
      9. Creating Documentation with RDoc
      10. Embedded Ruby
      11. Review Questions
    14. 11. A Short Guide to Ruby on Rails
      1. Where Did Rails Come From
      2. Why Rails?
      3. What Have Other Folks Done with Rails?
      4. Hosting Rails
      5. Installing Rails
      6. Learning Rails
      7. A Brief Tutorial
      8. Review Questions
    15. A. Ruby Reference
      1. Ruby Interpreter
      2. Ruby's Reserved Words
      3. Operators
      4. Escape Characters
      5. Predefined Variables
      6. Global Constants
      7. Regular Expressions
      8. String Unpack Directives
      9. Array Pack Directives
      10. Sprintf Flags and Field Types
      11. File Tests
      12. Time Formatting Directives
      13. RDoc Options
      14. Rake
    16. B. Answers to Review Questions
      1. Chapter 1 Review Questions
      2. Chapter 2 Review Questions
      3. Chapter 3 Review Questions
      4. Chapter 4 Review Questions
      5. Chapter 5 Review Questions
      6. Chapter 6 Review Questions
      7. Chapter 7 Review Questions
      8. Chapter 8 Review Questions
      9. Chapter 9 Review Questions
      10. Chapter 10 Review Questions
      11. Chapter 11 Review Questions
    17. Glossary
    18. Index
    19. About the Author
    20. Colophon
    21. SPECIAL OFFER: Upgrade this ebook with O’Reilly

Manipulating Strings

Here's a fun one to get started with. The * method repeats a string by an integer factor:

"A horse! " * 2 # => "A horse! A horse! "

You can concatenate a string to the result:

taf = "That's ".downcase * 3 + "all folks!" # => "that's that's that's all folks!"
taf.capitalize # => "That's that's that's all folks!"

Inserting a String in a String

The insert method lets you insert another string at a given index in a string. For example, you can correct spelling:

"Be carful.".insert 6, "e" # => "Be careful."

or add a word (plus a space):

"Be careful!".insert 3, "very " # => "Be very careful!"

or even throw the * method in just to prove that you can:

"Be careful!".insert 3, "very " * 5 # => "Be very very very very very careful!"

Changing All or Part of a String

You can alter all or part of a string, in place, with the []= method. (Like [], which is the counterpart of slice, []= is an alias of slice!, so anywhere you use []=, you can use slice!, with the same arguments.)

Given the following strings (some scoundrel has been editing our Shakespeare text):

line = "A Porsche! a Porsche! my kingdom for a Porsche!"
cite = "Act V, Scene V"
speaker = "King Richard, 2007"

enter a string as the argument to []=, and it will return the new, corrected string, if found; nil otherwise.

speaker[", 2007"]= "III" # => "III"
p speaker # => "King Richard III"

That's looking better.

If you specify a Fixnum (integer) as an index, it returns the corrected string you placed at the index location. (String lengths are automatically adjusted by Ruby if the replacement string is a different length than the original.)

cite[13]= "IV" # => "IV"
p cite # => "Act V, Scene IV"

At the index 13, []= found the substring V and replaced it with IV.

You can use an offset and length (two Fixnums) to tell []= the index of the substring where you want to start, and then how many characters you want to retrieve:

line[39,8]= "Porsche 911 Turbo!" # => "Porsche 911 Turbo!"
p line # => "A Porsche! a Porsche! my kingdom for a Porsche 911 Turbo!"

You started at index 39, and went 8 characters from there (inclusive).

You can also enter a range to indicate a range of characters you want to change. Include the last character with two dots (..):

speaker[13..15]= "the Third" # => "the Third"
p speaker # => "King Richard the Third"

You can also use regular expressions (see "Regular Expressions," later in this chapter), as shown here:

line[/Porsche!$/]= "Targa!" # => "Targa!"
p line # => "A Porsche! a Porsche! my kingdom for a Targa!"

The regular expression /Porsche!$/ matches if Porsche! appears at the end of the line ($). If this is true, the call to []= exchanges Porsche! with Targa!.

The chomp and chop Methods

The chop (or chop!) method chops off the last character of a string, and the chomp (chomp!) method chomps off the record separator ($/)—usually just a newline—from a string. Consider the string joe, a limerick created as a here document:

joe = <<limerick
There once was a fellow named Joe
quite fond of Edgar Allen Poe
   He read with delight
   Nearly half the night
When his wife said "Get up!" he said "No."
limerick # => "There once was a fellow named Joe\nquite fond of Edgar Allen
Poe\n   He read with delight\n   Nearly half the night\nWhen his wife said \"Get up!\"
he said \"No.\"\n"

Apply chomp! to remove the last record separator (\n):

joe.chomp! # => "There once was a fellow named Joe\nquite
fond of Edgar Allen Poe\n   He read with delight\n   Nearly half the
night\nWhen his wife said \"Get up!\" he said \"No.\""

Now apply it again, and chomp! returns nil without altering the string because there is no record separator at the end of the string:

joe.chomp! # => nil

chop, chomp's greedy twin, shows no mercy on the string, removing the last character (a quote) with abandon:

joe.chop! = "There once was a fellow named Joe\nquite fond of
Edgar Allen Poe\n   He read with delight\n   Nearly half the
night\nWhen his wife said \"Get up!\" he said \"No"

The delete Method

With delete or delete!, you can delete characters from a string:

"That's call folks!".delete "c" # => "That's all folks"

That looks easy, because there is only one occurrence of the letter c in the string, so you don't see any interesting side effects, as you would in the next example. Let's say you want to get rid of that extra l in alll:

"That's alll folks".delete "l" # => "That's a foks"

Oh, boy. It cleaned me out of all ls. I can't use delete the way I want, so how do I fix calll? What if I use two ls instead of one?

"That's alll folks".delete "ll" # => "That's a foks"

I got the same thing. (I knew I would.) That's because delete uses the intersection (what intersects or is the same in both) of its arguments to decide what part of the string to take out. The nifty thing about this, though, is you can also negate all or part of an argument with the caret (^), similar to its use in regular expressions:

"That's all folks".delete "abcdefghijklmnopqrstuvwxyz", "^ha" # => "haa"

The caret negates both the characters in the argument, not just the first one (you can do "^h^a", too, and get the same answer).

Substitute the Substring

Try gsub (or gsub!). This method replaces a substring (first argument) with a replacement string (second argument):

"That's alll folks".gsub "alll", "all" # => "That's all folks"

Or you might do it this way:

"That's alll folks".gsub "lll", "ll" # => "That's all folks"

The replace method replaces a string wholesale. Not just a substring, the whole thing.

call = "All hands on deck!"
call.replace "All feet on deck!" # => "All feet on deck!"

So why wouldn't you just do it this way?

call = "All hands on deck!"
call = "All feet on deck!"

Wouldn't you get the same result? Not exactly. When you use replace, call remains the same object, with the same object ID, but when you assign the string to call twice, the object and its ID will change. Just a subtlety you ought to know.

# same object
call = "All hands on deck!" # => "All hands on deck!"
call.object_id # => 1624370
call.replace "All feet on deck!" # => "All feet on deck!"
call.object_id # => 1624370

# different object
call = "All hands on deck!" # => "All hands on deck!"
call.object_id # => 1600420
call = "All feet on deck!" # => "All feet on deck!"
call.object_id # => 1009410

Turn It Around

To reverse the characters means to alter the characters so they read in the opposite direction. You can do this with the reverse method (or reverse! for permanent damage). Say you want to reverse the order of the English alphabet:

"abcdefghijklmnopqrstuvwxyz".reverse # => "zyxwvutsrqponmlkjihgfedcba"

Or, maybe you'd like to reverse a palindrome:

palindrome = "dennis sinned"
palindrome.reverse! # => "dennis sinned"
p palindrome

Not much harm done, even though reverse! changed the string in place. Think about that one for a while.

From a String to an Array

Conveniently, split converts a string to an array. The first call to split is without an argument:

"0123456789".split # => ["0123456789"]

That was easy, but what about splitting up all the individual values and converting them into elements? Do that with a regular expression (//) that cuts up the original string at the junction of characters.

"0123456789".split( // ) # => ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]

In the next example, the regular expression matches a comma and a space (/, /):

c_w = "George Jones, Conway Twitty, Lefty Frizzell, Ferlin Husky"
# => "George Jones, Conway Twitty, Lefty Frizzell, Ferlin Husky"
c_w.split(/, /) # => ["George Jones", "Conway Twitty",
"Lefty Frizzell", "Ferlin Husky"]

The best content for your career. Discover unlimited learning on demand for around $1/day.