The Ruby Way, 2nd ed.
Introduction
Preface to 2nd Edition
Using this Book
What is the "Ruby Way"?
Notes on 2nd Edition
Chapter 1: Ruby in Review
1.1 Some Words on Object Orientation
1.2 Basic Ruby Syntax and Semantics
1.2.1 Keywords and Identifiers
1.2.2 Comments and Embedded Documentation
1.2.3 Constants, Variables, and Types
1.2.4 Operators and Precedence
1.2.5 A Sample Program
1.2.6 Looping and Branching
1.2.7 Exceptions
1.3 OOP in Ruby
1.3.1 Objects
1.3.2 Built-in Classes
1.3.3 Modules and Mixins
1.3.4 Creating Classes
1.3.5 Methods and Attributes
1.4 Dynamic Aspects of Ruby
1.4.1 Coding at Runtime
1.4.2 Reflection
1.4.3 Missing Methods
1.4.4 Garbage Collection
1.5 Training Your Intuition: Things to Remember
1.5.1 Syntax Issues
1.5.2 Perspectives in Programming
1.5.3 Ruby's Case Statement
1.5.4 Rubyisms and Idioms
1.5.5 Expression Orientation and Other Miscellaneo...
1.6 Jargon and slang
1.7 Conclusion
Chapter 2: Manipulating Strings
2.1 Representing Ordinary Strings
2.2 Representing Strings with Alternate Notations
2.3 Using Here-Documents
2.4 Finding the Length of a String
2.5 Processing a Line at a Time
2.6 Processing a Byte at a Time
2.7 Performing Specialized String Comparisons
2.8 Tokenizing a String
2.9 Formatting a String
2.10 Using Strings as IO Objects (StringIO)
2.11 Controlling Uppercase and Lowercase
2.12 Accessing and Assigning Substrings
2.13 Substituting in Strings
2.14 Searching a String
2.15 Converting Between Characters and ASCII Codes
2.16 Implicit and Explicit Conversion (to_s, to_str)
2.17 Appending an Item onto a String
2.18 Removing Trailing Newlines and Other Characters
2.19 Trimming Whitespace from a String
2.20 Repeating Strings
2.21 Embedding Expressions Within Strings
2.22 Delayed Interpolation of Strings
2.23 Parsing Comma-Separated Data
2.24 Converting Strings to Numbers (Decimal and Otherwise)
2.25 Encoding and Decoding rot13 Text
2.26 Encrypting a String
2.27 Compressing a String
2.28 Counting Characters in Strings
2.29 Reversing a String
2.30 Removing Duplicate Characters
2.31 Removing Specific Characters
2.32 Printing Special Characters
2.33 Generating Successive Strings
2.34 Calculating a 32-bit CRC
2.35 Calculating the MD5 Hash of a String
2.36 Calculate the Levenshtein Distance Between Two Strings
2.37 Encoding and decoding base64 Strings
2.38 Encoding and Decoding Strings (uuencode/uud...
2.39 Expanding and Compressing Tab Characters
2.40 Wrapping Lines of Text
2.41 Conclusion
Chapter 3: Manipulating Regular Expressions
3.1 Regular Expression Syntax
3.2 Compiling Regular Expressions
3.3 Escaping Special Characters
3.4 Using Anchors
3.5 Using Quantifiers
3.6 Positive and Negative Lookahead
3.7 Accessing Backreferences
3.8 Using Character Classes
3.9 Extended Regular Expressions
3.10 Matching a Newline with a Dot
3.11 Using Embedded Options
3.12 Using Embedded Sub-expressions
3.13 Ruby and Oniguruma
3.13.1 Testing the Presence of Oniguruma
3.13.2 Building Oniguruma
3.13.3 A Few New Features of Oniguruma
3.13.4 Positive and Negative Lookbehind
3.13.5 More on Quantifiers
3.13.6 Named Matches
3.13.7 Recursion in Regular Expressions
3.14 A Few Sample Regular Expressions
3.14.1 Matching an IP address
3.14.2 Matching a Keyword-Value Pair
3.14.3 Matching Roman Numerals
3.14.4 Matching Numeric Constants
3.14.5 Matching a Date-time String
3.14.6 Detecting Doubled Words in Text
3.14.7 Matching All-caps Words
3.14.8 Matching Version Numbers
3.14.9 A Few Other Patterns
3.15 Conclusion
Chapter 4: Internationalization in Ruby
4.1 Overview
4.2 Coding in a Post-ASCII World
4.2.1 The jcode Library and $KCODE
4.2.2 Revisiting Common String and Regex Operations
4.2.3 Detecting Character Encodings
4.2.4 Normalizing Unicode Strings
4.2.5 Issues in String Collation
4.2.6 Converting Between Encodings
4.3 Using Message Catalogs
4.3.1 Overview
4.3.2 Getting Started with Message Catalogs
4.3.3 A Simple Example
4.3.4 Other Notes
4.4 Conclusion
Chapter 5: Performing Numerical Calculations
5.1 Representing Numbers in Ruby
5.2 Basic Operations on Numbers
5.3 Rounding Floating Point Values
5.4 Comparing Floating Point Numbers
5.5 Formatting Numbers for Output
5.6 Formatting Numbers with Commas
5.7 Working with Very Large Numbers
5.8 Using BigDecimal
5.9 Working with Rational Values
5.10 Matrix Manipulation
5.11 Working with Complex Numbers
5.12 Using mathn
5.13 Finding Prime Factorization, GCD, and LCM
5.14 Working with Prime Numbers
5.15 Implicit and Explicit Numeric Conversion
5.16 Coercing Numeric Values
5.17 Performing Bit-level Operations on Numbers
5.18 Performing Base Conversions
5.19 Finding Cube Roots, Fourth Roots, etc.
5.20 Determining the Architecture's Byte Order
5.21 Numerical Computation of a Definite Integral
5.22 Trigonometry in Degrees, Radians, and Grads
5.23 More Advanced Trigonometry
5.24 Finding Logarithms with Arbitrary Bases
5.25 Finding the Mean, Median, and Mode of a Data Set
5.26 Finding Variance and Standard Deviation
5.27 Finding a Correlation Coefficient
5.28 Generating Random Numbers
5.29 Caching Functions with memoize
5.30 Conclusion
Chapter 6: Using Symbols and Ranges
6.1 Symbols
6.1.1 Symbols as Enumerations
6.1.2 Symbols as Meta-values
6.1.3 Symbols, Variables, and Methods
6.1.4 Converting To/from Symbols
6.2 Ranges
6.2.1 Open and Closed Ranges
6.2.2 Finding Endpoints
6.2.3 Iterating over Ranges
6.2.4 Testing Range Membership
6.2.5 Converting to Arrays
6.2.6 Backward Ranges
6.2.7 The Flip-flop Operator
6.2.8 Custom Ranges
6.3 Conclusion
Chapter 7: Manipulating Times and Dates
7.1 Determining the Current Time
7.2 Working with Specific Times (Post-epoch)
7.3 Determining Day of the Week
7.4 Determining the Date of Easter
7.5 Finding the Nth Weekday in a Month
7.6 Converting Between Seconds and Larger Units
7.7 Converting to and from the Epoch
7.8 Working with Leap Seconds: Don't!
7.9 Finding the Day of the Year
7.10 Validating a Date/Time
7.11 Finding the Week of the Year
7.12 Detecting Leap Years
7.13 Obtaining the Time Zone
7.14 Working with Hours and Minutes Only
7.15 Comparing Date/Time Values
7.16 Adding Intervals to Date/Time Values
7.17 Computing the Difference in two date/time Values
7.18 Working with Specific Dates (Pre-epoch)
7.19 Interconverting Between Time, Date, and DateTime
7.20 Retrieving a Date/Time Value from a String
7.21 Formatting and Printing Date/Time Values
7.22 Time Zone Conversions
7.23 Determining the Number of Days in a Month
7.24 Dividing a Month into Weeks
7.25 Date and Time vs. DateTime
7.26 Conclusion
Chapter 8: Arrays, Hashes, and Other Enumerables
8.1 Working with Arrays
8.1.1 Creating and Initializing an Array
8.1.2 Accessing and Assigning Elements
8.1.3 Finding an Array's Size
8.1.4 Comparing Arrays
8.1.5 Sorting an Array
8.1.6 Selecting from an Array by Criteria
8.1.7 Using Specialized Indexing Functions
8.1.8 Implementing a Sparse Matrix
8.1.9 Using Arrays as Mathematical Sets
8.1.10 Randomizing an Array
8.1.11 Using Multidimensional Arrays
8.1.12 Finding Elements in One Array but Not Another
8.1.13 Transforming or Mapping Arrays
8.1.14 Removing nil Values from an Array
8.1.15 Removing Specific Array Elements
8.1.16 Concatenating and Appending
8.1.17 Iterating Over an Array
8.1.18 Interposing Delimiters to Form a String
8.1.19 Reversing an Array
8.1.20 Removing Duplicate Elements
8.1.21 Interleaving Arrays
8.1.22 Counting Frequency of Values in an Array
8.1.23 Inverting an Array to Form a Hash
8.1.24 Synchronized Sorting of Multiple Arrays
8.1.25 Establishing a Default Value for New Array Elements
8.2 Working with Hashes
8.2.1 Creating a New Hash
8.2.2 Specifying a Default Value
8.2.3 Accessing and Adding Key-Value Pairs
8.2.4 Deleting Key-Value Pairs
8.2.5 Iterating Over a Hash
8.2.6 Inverting a Hash
8.2.7 Detecting Keys and Values
8.2.8 Extracting Hashes into Arrays
8.2.9 Selecting Key-Value Pairs by Criteria
8.2.10 Sorting a Hash
8.2.11 Merging Two Hashes
8.2.12 Creating a Hash from an Array
8.2.13 Finding Differences or Intersections of Hash Keys
8.2.14 Using a Hash as a Sparse Matrix
8.2.15 Implementing a Hash with Duplicate Keys
8.3 Enumerable Collections in General
8.3.1 The inject Method
8.3.2 Using Quantifiers
8.3.3 The partitition Method
8.3.4 Iterating by Groups
8.3.5 Converting to Arrays or Sets
8.3.6 Using Enumerator Objects
8.3.7 Using Generator Objects
8.4 Conclusion
Chapter 9: More Advanced Data Structures
9.1 Working with Sets
9.1.1 Simple Set Operations
9.1.2 More Advanced Set Operations
9.2 Working with Stacks and Queues
9.2.1 Implementing a Stricter Stack
9.2.2 Detecting Unbalanced Punctuation
9.2.3 Understanding Stacks and Recursion
9.2.4 Implementing a Stricter Queue
9.3 Working with Trees
9.3.1 Implementing a Binary Tree
9.3.2 Sorting Using a Binary Tree
9.3.3 A Binary Tree as a Lookup Table
9.3.4 Converting a Tree to a String or Array
9.4 Working with Graphs
9.4.1 Implementing a Graph as an Adjacency Matrix
9.4.2 Determining Whether a Graph is Fully Connected
9.4.3 Determining Whether a Graph has an Euler Circuit
9.4.4 Determining Whether a Graph has an Euler Path
9.4.5 Graph Tools in Ruby
9.5 Conclusion
Chapter 10: Manipulating files and external data
10.1 I/O and Data Storage
10.1.1 Opening and Closing Files
10.1.2 Updating a File
10.1.3 Appending to a File
10.1.4 Random Access to Files
10.1.5 Working with Binary Files
10.1.6 Locking Files
10.1.7 Performing Simple I/O
10.1.8 Performing Buffered and Unbuffered I/O
10.1.9 Manipulating File Ownership and Permissions
10.1.10 Retrieving and Setting Timestamp Information
10.1.11 Checking File Existence and Size
10.1.12 Checking Special File Characteristics
10.1.13 Working with Pipes
10.1.14 Performing Special I/O Operations
10.1.15 Non-blocking I/O and Threads
10.1.16 Using readpartial
10.1.17 Manipulating Pathnames
10.1.18 Using the Pathname Class
10.1.19 Command-level File Manipulation
10.1.20 Grabbing Characters From the Keyboard
10.1.21 Reading an Entire File into Memory
10.1.22 Iterating Over a File by Lines
10.1.23 Iterating Over a File by Byte
10.1.24 Using Strings as IO Objects
10.1.25 Reading Data Embedded in a Program
10.1.26 Reading Program Source
10.1.27 Working with Temporary Files
10.1.28 Changing and Setting the Current Directory
10.1.29 Changing the Current Root
10.1.30 Iterating Over Directory Entries
10.1.31 Getting a List of Directory Entries
10.1.32 Creating a Chain of Directories
10.1.33 Deleting a Directory Recursively
10.1.34 Finding Files and Directories
10.2 Performing Higher-Level Data Access
10.2.1 Simple Marshaling
10.2.2 More Complex Marshaling
10.2.3 Performing Limited "Deep Copying" Using Marshal
10.2.4 Better Object Persistence with PStore
10.2.5 Working with CSV Data
10.2.6 Marshaling with YAML
10.2.7 Using Madeleine
10.2.8 Using the DBM Library
10.2.9 Using KirbyBase
10.3 Connecting to External Databases
10.3.1 Interfacing to SQLite
10.3.2 Interfacing to MySQL
10.3.3 Interfacing to PostgreSQL
10.3.4 Interfacing to LDAP
10.3.5 Interfacing to Oracle
10.3.6 Using the DBI Wrapper
10.3.7 Object-Relational Mappers (ORMs)
10.4 Conclusion
Chapter 11: Ruby and OOP
11.1 Everyday OOP Tasks
11.1.1 Using Multiple Constructors
11.1.2 Creating Instance Attributes
11.1.3 More Elaborate Constructors
11.1.4 Creating Class-Level Attributes and Methods
11.1.5 Inheriting from a Superclass
11.1.6 Testing Classes of Objects
11.1.7 Testing Equality of Objects
11.1.8 Controlling Access to Methods
11.1.9 Copying an Object
11.1.10 Using initialize_copy
11.1.11 Understanding allocate
11.1.12 Working with Modules
11.1.13 Transforming or Converting Objects
11.1.14 Creating Data-Only Classes (Structs)
11.1.15 Freezing Objects
11.2 More Advanced Techniques
11.2.1 Sending an Explicit Message to an Object
11.2.2 Specializing an Individual Object
11.2.3 Nesting Classes and Modules
11.2.4 Creating Parametric Classes
11.2.5 Storing Code as Objects
11.2.6 How Module Inclusion Works
11.2.7 Detecting Default Parameters
11.2.8 Forwarding and Delegating
11.2.9 Class-Level Readers and Writers
11.2.10 Working in Advanced Programming Disciplines
11.3 Working with Other Dynamic Features
11.3.1 Evaluating Code Dynamically
11.3.2 Using const_get
11.3.3 Dynamically Instantiating a Class by Name
11.3.4 Getting and Setting Instance Variables
11.3.5 Using define_method
11.3.6 Using const_missing
11.3.7 Removing Definitions
11.3.8 Obtaining Lists of Defined Entities
11.3.9 Examining the Call Stack
11.3.10 Monitoring Execution of a Program
11.3.11 Traversing the Object Space
11.3.12 Tracking Changes to a Class or Object Defini...
11.3.13 Defining Finalizers for Objects
11.4 Conclusion
Chapter 12: Graphical Interfaces for Ruby
12.1 Ruby/Tk
12.1.1 Overview
12.1.2 A Simple Windowed Application
12.1.3 Working with Buttons
12.1.4 Working with Text Fields
12.1.5 Working with Other Widgets
12.1.6 Other Notes
12.2 Ruby/GTK
12.2.1 Overview
12.2.2 A Simple Windowed Application
12.2.3 Working with Buttons
12.2.4 Working with Text Fields
12.2.5 Working with Other Widgets
12.2.6 Other Notes
12.3 FXRuby (FOX)
12.3.1 Overview
12.3.2 A Simple Windowed Application
12.3.3 Working with Buttons
12.3.4 Working with Text Fields
12.3.5 Working with Other Widgets
12.3.6 Other Notes
12.4 QtRuby
12.4.1 Overview
12.4.2 A Simple Windowed Application
12.4.3 Working with Buttons
12.4.4 Working with Text Fields
12.4.5 Working with Other Widgets
12.4.6 Other Notes
12.5 Others
12.5.1 Ruby and X
12.5.2 Ruby and wxWindows
12.5.3 Apollo? (Ruby and Delphi)
12.5.4 Ruby and the Windows API
12.6 Conclusion
Chapter 13: Threads in Ruby
13.1 Creating and Manipulating Threads
13.1.1 Creating Threads
13.1.2 Accessing Thread-Local Variables
13.1.3 Querying and Changing Thread Status
13.1.4 Achieving a Rendezvous (and Capturing a Retu...
13.1.5 Dealing with Exceptions
13.1.6 Using a Thread Group
13.2 Synchronizing Threads
13.2.1 Performing Simple Synchronization with Criti...
13.2.2 Synchronizing Access to Resources (mutex.rb)
13.2.3 Using the Predefined Synchronized Queue Classes
13.2.4 Using Condition Variables
13.2.5 Using Other Synchronization Techniques (moni...
13.2.6 Allowing Timeout of an Operation
13.2.7 Waiting for an Event
13.2.8 Continuing Processing during I/O
13.2.9 Implementing Parallel Iterators
13.2.10 Recursive Deletion in Parallel
13.3 Conclusion
Chapter 14: System Administration and Scripting
14.1 Running External Programs
14.1.1 Using system and exec
14.1.2 Command Output Substitution
14.1.3 Manipulating Processes
14.1.4 Manipulating Standard Input/Output
14.2 Command-line Options and Arguments
14.2.1 Parsing Command Line Options
14.2.2 Working with ARGF
14.2.3 Working with ARGV
14.3 The Shell library
14.3.1 Using Shell for I/O Redirection
14.3.2 Other Notes on shell.rb
14.4 Accessing Environment Variables
14.5 Windows
14.5.1 Using Win32API
14.5.2 Using Win32OLE
14.5.3 Using ActiveScriptRuby
14.5.4 The Windows One-click Installer
14.5.5 Single-file Executables
14.5.6 Libaries You Should Know About
14.6 Working with Files, Directories, and Trees
14.6.1 A Few Words on Text Filters
14.6.2 Copying a Directory Tree (With Symlinks)
14.6.3 Deleting Files by Age or Other Criteria
14.6.4 Determining Free Space on a Disk
14.7 Other
14.7.1 Piping into the Ruby Interpreter
14.7.2 Getting and Setting Exit Codes
14.7.3 Testing Whether a Program is Running Interac...
14.7.4 Determining the Current Platform or Operatin...
14.7.5 Using the Etc Module
14.7.6 Libraries and Utilities You Should Know About
14.8 Conclusion
Chapter 15: Ruby and Data Formats
15.1 Parsing XML with REXML
15.2 Using YAML
15.3 Working with RSS and Atom
15.4 Manipulating Image Data (RMagick)
15.5 Ruby and Flash
15.6 Writing PDF files
15.7 Manipulating Color Data in Documents and Images
15.8 Conclusion
Chapter 16: Testing and Debugging
16.1 Using irb
16.2 Testing with Test::Unit
16.3 Using xmp
16.4 Prettyprinting Objects
16.5 Measuring Code Coverage
16.6 Using $-v and Other Globals
16.7 Performance Issues
16.8 Conclusion
Chapter 17: Packaging and Distributing Code
17.1 RDoc and Documentation in General
17.2 Installation and Packaging
17.3 RubyGems
17.4 Distribution Options
17.5 RubyForge and the RAA
17.6 Conclusion
Chapter 18: Network Programming
18.1 Network Servers
18.1.1 A Simple Server: Time of Day
18.1.2 Implementing a Threaded Server
18.1.3 Case Study: A Peer-to-peer Chess Server
18.2 Network Clients
18.2.1 Retrieving Truly Random Numbers from the Web
18.2.2 Contacting an Official Timeserver
18.2.3 Interacting with a POP Server
18.2.4 Encoding/Decoding Email Attachments
18.2.5 Interacting with an IMAP Server
18.2.6 Case study: A Mail-News Gateway
18.2.7 Retrieving a Document from a Specified URL
18.2.8 Using OpenURI
18.3 Conclusion
Chapter 19: Ruby and Web Applications
19.1 Overview: Using the cgi Library
19.2 Working with Cookies
19.3 Working with User Sessions
19.4 Displaying and Processing Forms
19.5 Using fastcgi.rb
19.6 Ruby on Rails
19.6.1 Introduction
19.6.2 Principles and Techniques
19.6.3 Two ways of Scaffolding
19.6.4 Debugging Rails Apps
19.6.5 Apps without Databases
19.6.6 Core Extensions
19.6.7 Related Tools and Libs
19.7 Nitro
19.8 Introduction
19.9 Principles and Techniques
19.10 Other Web Frameworks
19.11 Ruby and the Web Server
19.11.1 Using WEBrick
19.11.2 Using mod_ruby
19.11.3 Using eruby
19.12 Ruby and Web Services
19.12.1 SOAP
19.12.2 REST
19.13 Conclusion
Chapter 20: Distributed Ruby
20.1 An overview: Using dRuby
20.1.1 Case Study: A Stock Ticker Simulation
20.1.2 More on dRuby
20.2 XML-RPC
20.3 Okay (YAML)
20.4 Rinda and Ring
20.5 Conclusion
Chapter 21: Ruby and External Software
21.1 Understanding Rake
21.2 Understanding mkmf and extconf.rb
21.3 Embedding a Ruby Interpreter into a C/C++ Program
21.4 Making Ruby a DLL-able Plugin for Another Program
21.5 Using SWIG with Ruby
21.6 Ruby/DL
21.7 Interfacing with gnuplot
21.8 Ruby and Mozilla
21.9 Ruby and Java
21.10 Ruby and .NET
21.11 Conclusion
Chapter 22: Ruby Development Tools
22.1 RubyGems
22.1.1 Basic Usage
22.1.2 Running a Gem Server
22.1.3 Writing a Gem Spec
22.2 RDoc
22.2.1 Overview
22.2.2 Customizing
22.2.3 Templating
22.3 The ri Utility
22.4 Editor Support
22.4.1 vim
22.4.2 emacs
22.4.3 Others
22.5 Integrated Development Environments
22.5.1 FreeRIDE
22.5.2 RDE
22.5.3 ArachnoRuby
22.5.4 Eclipse
22.5.5 Komodo
22.6 Conclusion
Chapter 23: The Ruby Community
23.1 Web Resources
23.2 Newsgroup and Mailing Lists
23.3 Blogs and Online Magazines
23.4 Ruby Change Requests (RCRs)
23.5 IRC Channels
23.6 Ruby Conferences
23.7 Local Ruby Groups
23.8 Conclusion