You are previewing The Ruby Way: Solutions and Techniques in Ruby Programming, Third Edition.
O'Reilly logo
The Ruby Way: Solutions and Techniques in Ruby Programming, Third Edition

Book Description

For more than a decade, Ruby developers have turned to The Ruby Way for reliable “how-to” guidance on effective Ruby programming. Now, Hal Fulton and André Arko have thoroughly updated this classic guide to cover new language enhancements and developers’ experiences through Ruby 2.1.

The new edition illuminates Ruby 2.1 through 400+ examples, each answering the question: “How do I do this in Ruby?” For each example, they present both a task description and realistic technical constraints. Next, they walk step-by-step through presenting one good solution, offering detailed explanations to promote deeper understanding.

Conveniently organized by topic, The Ruby Way, Third Edition makes it easier than ever to find the specific solution you want—and to write better code by reflecting Ruby’s unique philosophy and spirit.

Coverage includes

  • Ruby 2.1 overview: terminology, philosophy, and basic principles

  • Best practices for strings and regular expressions

  • Efficiently internationalizing your code

  • Performing calculations (including trigonometry, calculus, statistics, and time/date calculations)

  • Working with “Rubyesque” objects such as symbols and ranges

  • Using arrays, hashes, stacks, queues, trees, graphs, and other data structures

  • Efficiently storing data with YAML, JSON, and SQLite3

  • Leveraging object-oriented and dynamic features, from multiple constructors to program inspection

  • Building GUIs with Shoes 4, Ruby/Tk, Ruby/GTK3, QtRuby, and other toolkits

  • Improving thread performance by understanding Ruby’s synchronization methods and avoiding its pitfalls

  • Automating system administration with Ruby

  • Data formats: JSON, XML, RSS, Atom, RMagick, PDF, and more

  • Testing and debugging with RSpec, Minitest, Cucumber, byebug, and pry

  • Measuring Ruby program performance

  • Packaging and distributing code, and managing dependencies with Bundler

  • Network programming: clients, time servers, POP, SMTP, IMAP, Open-URI

  • Web applications: HTTP servers, Rails, Sinatra, HTML generation, and more

  • Writing distributed Ruby software with drb

  • Choosing modern development tools that maximize your productivity

  • All source code for this book may be downloaded at www.rubyhacker.com.

    informit.com/aw

    informit.com/ruby

    rubyhacker.com/therubyway

    therubyway.io

    Table of Contents

    1. About This eBook
    2. Title Page
    3. Copyright Page
    4. Praise for The Ruby Way, Third Edition
    5. Praise for Previous Editions of The Ruby Way
    6. Dedication Page
    7. Contents
    8. Foreword
      1. Foreword to the Third Edition
      2. Foreword to the Second Edition
      3. Foreword to the First Edition
    9. Acknowledgments
      1. Acknowledgments for the Third Edition
      2. Acknowledgments for the Second Edition
      3. Acknowledgments for the First Edition
    10. About the Authors
    11. Introduction
      1. About the Third Edition
      2. How This Book Works
      3. About the Book’s Source Code
      4. What Is the “Ruby Way”?
    12. Chapter 1. Ruby in Review
      1. 1.1 An Introduction to Object Orientation
        1. 1.1.1 What Is an Object?
        2. 1.1.2 Inheritance
        3. 1.1.3 Polymorphism
        4. 1.1.4 A Few More Terms
      2. 1.2 Basic Ruby Syntax and Semantics
        1. 1.2.1 Keywords and Identifiers
        2. 1.2.2 Comments and Embedded Documentation
        3. 1.2.3 Constants, Variables, and Types
        4. 1.2.4 Operators and Precedence
        5. 1.2.5 A Sample Program
        6. 1.2.6 Looping and Branching
        7. 1.2.7 Exceptions
      3. 1.3 OOP in Ruby
        1. 1.3.1 Objects
        2. 1.3.2 Built-in Classes
        3. 1.3.3 Modules and Mixins
        4. 1.3.4 Creating Classes
        5. 1.3.5 Methods and Attributes
      4. 1.4 Dynamic Aspects of Ruby
        1. 1.4.1 Coding at Runtime
        2. 1.4.2 Reflection
        3. 1.4.3 Missing Methods
        4. 1.4.4 Garbage Collection
      5. 1.5 Training Your Intuition: Things to Remember
        1. 1.5.1 Syntax Issues
        2. 1.5.2 Perspectives in Programming
        3. 1.5.3 Ruby’s case Statement
        4. 1.5.4 Rubyisms and Idioms
        5. 1.5.5 Expression Orientation and Other Miscellaneous Issues
      6. 1.6 Ruby Jargon and Slang
      7. 1.7 Conclusion
    13. Chapter 2. Working with Strings
      1. 2.1 Representing Ordinary Strings
      2. 2.2 Representing Strings with Alternate Notations
      3. 2.3 Using Here-Documents
      4. 2.4 Finding the Length of a String
      5. 2.5 Processing a Line at a Time
      6. 2.6 Processing a Character or Byte at a Time
      7. 2.7 Performing Specialized String Comparisons
      8. 2.8 Tokenizing a String
      9. 2.9 Formatting a String
      10. 2.10 Using Strings as IO Objects
      11. 2.11 Controlling Uppercase and Lowercase
      12. 2.12 Accessing and Assigning Substrings
      13. 2.13 Substituting in Strings
      14. 2.14 Searching a String
      15. 2.15 Converting Between Characters and ASCII Codes
      16. 2.16 Implicit and Explicit Conversion
      17. 2.17 Appending an Item onto a String
      18. 2.18 Removing Trailing Newlines and Other Characters
      19. 2.19 Trimming Whitespace from a String
      20. 2.20 Repeating Strings
      21. 2.21 Embedding Expressions within Strings
      22. 2.22 Delayed Interpolation of Strings
      23. 2.23 Parsing Comma-Separated Data
      24. 2.24 Converting Strings to Numbers (Decimal and Otherwise)
      25. 2.25 Encoding and Decoding rot13 Text
      26. 2.26 Encrypting Strings
      27. 2.27 Compressing Strings
      28. 2.28 Counting Characters in Strings
      29. 2.29 Reversing a String
      30. 2.30 Removing Duplicate Characters
      31. 2.31 Removing Specific Characters
      32. 2.32 Printing Special Characters
      33. 2.33 Generating Successive Strings
      34. 2.34 Calculating a 32-Bit CRC
      35. 2.35 Calculating the SHA-256 Hash of a String
      36. 2.36 Calculating the Levenshtein Distance Between Two Strings
      37. 2.37 Encoding and Decoding Base64 Strings
      38. 2.38 Expanding and Compressing Tab Characters
      39. 2.39 Wrapping Lines of Text
      40. 2.40 Conclusion
    14. Chapter 3. Working with Regular Expressions
      1. 3.1 Regular Expression Syntax
      2. 3.2 Compiling Regular Expressions
      3. 3.3 Escaping Special Characters
      4. 3.4 Using Anchors
      5. 3.5 Using Quantifiers
      6. 3.6 Positive and Negative Lookahead
      7. 3.7 Positive and Negative Lookbehind
      8. 3.8 Accessing Backreferences
      9. 3.9 Named Matches
      10. 3.10 Using Character Classes
      11. 3.11 Extended Regular Expressions
      12. 3.12 Matching a Newline with a Dot
      13. 3.13 Using Embedded Options
      14. 3.14 Using Embedded Subexpressions
        1. 3.14.1 Recursion in Regular Expressions
      15. 3.15 A Few Sample Regular Expressions
        1. 3.15.1 Matching an IP Address
        2. 3.15.2 Matching a Keyword-Value Pair
        3. 3.15.3 Matching Roman Numerals
        4. 3.15.4 Matching Numeric Constants
        5. 3.15.5 Matching a Date/Time String
        6. 3.15.6 Detecting Doubled Words in Text
        7. 3.15.7 Matching All-Caps Words
        8. 3.15.8 Matching Version Numbers
        9. 3.15.9 A Few Other Patterns
      16. 3.16 Conclusion
    15. Chapter 4. Internationalization in Ruby
      1. 4.1 Background and Terminology
      2. 4.2 Working with Character Encodings
        1. 4.2.1 Normalization
        2. 4.2.2 Encoding Conversions
        3. 4.2.3 Transliteration
        4. 4.2.4 Collation
      3. 4.3 Translations
        1. 4.3.1 Defaults
        2. 4.3.2 Namespaces
        3. 4.3.3 Interpolation
        4. 4.3.4 Pluralization
      4. 4.4 Localized Formatting
        1. 4.4.1 Dates and Times
        2. 4.4.2 Numbers
        3. 4.4.3 Currencies
      5. 4.5 Conclusion
    16. Chapter 5. Performing Numerical Calculations
      1. 5.1 Representing Numbers in Ruby
      2. 5.2 Basic Operations on Numbers
      3. 5.3 Rounding Floating Point Values
      4. 5.4 Comparing Floating Point Numbers
      5. 5.5 Formatting Numbers for Output
      6. 5.6 Formatting Numbers with Commas
      7. 5.7 Working with Very Large Integers
      8. 5.8 Using BigDecimal
      9. 5.9 Working with Rational Values
      10. 5.10 Matrix Manipulation
      11. 5.11 Working with Complex Numbers
      12. 5.12 Using mathn
      13. 5.13 Finding Prime Factorization, GCD, and LCM
      14. 5.14 Working with Prime Numbers
      15. 5.15 Implicit and Explicit Numeric Conversion
      16. 5.16 Coercing Numeric Values
      17. 5.17 Performing Bit-Level Operations on Numbers
      18. 5.18 Performing Base Conversions
      19. 5.19 Finding Cube Roots, Fourth Roots, and So On
      20. 5.20 Determining the Architecture’s Byte Order
      21. 5.21 Numerical Computation of a Definite Integral
      22. 5.22 Trigonometry in Degrees, Radians, and Grads
      23. 5.23 Finding Logarithms with Arbitrary Bases
      24. 5.24 Finding the Mean, Median, and Mode of a Data Set
      25. 5.25 Variance and Standard Deviation
      26. 5.26 Finding a Correlation Coefficient
      27. 5.27 Generating Random Numbers
      28. 5.28 Caching Functions with Memoization
      29. 5.29 Conclusion
    17. Chapter 6. Symbols and Ranges
      1. 6.1 Symbols
        1. 6.1.1 Symbols as Enumerations
        2. 6.1.2 Symbols as Metavalues
        3. 6.1.3 Symbols, Variables, and Methods
        4. 6.1.4 Converting to/from Symbols
      2. 6.2 Ranges
        1. 6.2.1 Open and Closed Ranges
        2. 6.2.2 Finding Endpoints
        3. 6.2.3 Iterating Over Ranges
        4. 6.2.4 Testing Range Membership
        5. 6.2.5 Converting to Arrays
        6. 6.2.6 Backward Ranges
        7. 6.2.7 The Flip-Flop Operator
        8. 6.2.8 Custom Ranges
      3. 6.3 Conclusion
    18. Chapter 7. Working with Times and Dates
      1. 7.1 Determining the Current Time
      2. 7.2 Working with Specific Times (Post-Epoch)
      3. 7.3 Determining the Day of the Week
      4. 7.4 Determining the Date of Easter
      5. 7.5 Finding the Nth Weekday in a Month
      6. 7.6 Converting Between Seconds and Larger Units
      7. 7.7 Converting to and from the Epoch
      8. 7.8 Working with Leap Seconds: Don’t!
      9. 7.9 Finding the Day of the Year
      10. 7.10 Validating a Date or Time
      11. 7.11 Finding the Week of the Year
      12. 7.12 Detecting Leap Years
      13. 7.13 Obtaining the Time Zone
      14. 7.14 Working with Hours and Minutes Only
      15. 7.15 Comparing Time Values
      16. 7.16 Adding Intervals to Time Values
      17. 7.17 Computing the Difference in Two Time Values
      18. 7.18 Working with Specific Dates (Pre-Epoch)
      19. 7.19 Time, Date, and DateTime
      20. 7.20 Parsing a Date or Time String
      21. 7.21 Formatting and Printing Time Values
      22. 7.22 Time Zone Conversions
      23. 7.23 Determining the Number of Days in a Month
      24. 7.24 Dividing a Month into Weeks
      25. 7.25 Conclusion
    19. Chapter 8. Arrays, Hashes, and Other Enumerables
      1. 8.1 Working with Arrays
        1. 8.1.1 Creating and Initializing an Array
        2. 8.1.2 Accessing and Assigning Array Elements
        3. 8.1.3 Finding an Array’s Size
        4. 8.1.4 Comparing Arrays
        5. 8.1.5 Sorting an Array
        6. 8.1.6 Selecting from an Array by Criteria
        7. 8.1.7 Using Specialized Indexing Functions
        8. 8.1.8 Implementing a Sparse Matrix
        9. 8.1.9 Using Arrays as Mathematical Sets
        10. 8.1.10 Randomizing an Array
        11. 8.1.11 Using Multidimensional Arrays
        12. 8.1.12 Finding Elements in One Array But Not Another
        13. 8.1.13 Transforming or Mapping Arrays
        14. 8.1.14 Removing nil Values from an Array
        15. 8.1.15 Removing Specific Array Elements
        16. 8.1.16 Concatenating and Appending onto Arrays
        17. 8.1.17 Using an Array as a Stack or Queue
        18. 8.1.18 Iterating over an Array
        19. 8.1.19 Interposing Delimiters to Form a String
        20. 8.1.20 Reversing an Array
        21. 8.1.21 Removing Duplicate Elements from an Array
        22. 8.1.22 Interleaving Arrays
        23. 8.1.23 Counting Frequency of Values in an Array
        24. 8.1.24 Inverting an Array to Form a Hash
        25. 8.1.25 Synchronized Sorting of Multiple Arrays
        26. 8.1.26 Establishing a Default Value for New Array Elements
      2. 8.2 Working with Hashes
        1. 8.2.1 Creating a New Hash
        2. 8.2.2 Specifying a Default Value for a Hash
        3. 8.2.3 Accessing and Adding Key-Value Pairs
        4. 8.2.4 Deleting Key-Value Pairs
        5. 8.2.5 Iterating Over a Hash
        6. 8.2.6 Inverting a Hash
        7. 8.2.7 Detecting Keys and Values in a Hash
        8. 8.2.8 Extracting Hashes into Arrays
        9. 8.2.9 Selecting Key-Value Pairs by Criteria
        10. 8.2.10 Sorting a Hash
        11. 8.2.11 Merging Two Hashes
        12. 8.2.12 Creating a Hash from an Array
        13. 8.2.13 Finding Difference or Intersection of Hash Keys
        14. 8.2.14 Using a Hash as a Sparse Matrix
        15. 8.2.15 Implementing a Hash with Duplicate Keys
        16. 8.2.16 Other Hash Operations
      3. 8.3 Enumerables in General
        1. 8.3.1 The inject Method
        2. 8.3.2 Using Quantifiers
        3. 8.3.3 The partition Method
        4. 8.3.4 Iterating by Groups
        5. 8.3.5 Converting to Arrays or Sets
        6. 8.3.6 Using Enumerator Objects
      4. 8.4 More on Enumerables
        1. 8.4.1 Searching and Selecting
        2. 8.4.2 Counting and Comparing
        3. 8.4.3 Iterating
        4. 8.4.4 Extracting and Converting
        5. 8.4.5 Lazy Enumerators
      5. 8.5 Conclusion
    20. Chapter 9. More Advanced Data Structures
      1. 9.1 Working with Sets
        1. 9.1.1 Simple Set Operations
        2. 9.1.2 More Advanced Set Operations
      2. 9.2 Working with Stacks and Queues
        1. 9.2.1 Implementing a Stricter Stack
        2. 9.2.2 Detecting Unbalanced Punctuation in Expressions
        3. 9.2.3 Understanding Stacks and Recursion
        4. 9.2.4 Implementing a Stricter Queue
      3. 9.3 Working with Trees
        1. 9.3.1 Implementing a Binary Tree
        2. 9.3.2 Sorting Using a Binary Tree
        3. 9.3.3 Using a Binary Tree as a Lookup Table
        4. 9.3.4 Converting a Tree to a String or Array
      4. 9.4 Working with Graphs
        1. 9.4.1 Implementing a Graph as an Adjacency Matrix
        2. 9.4.2 Determining Whether a Graph Is Fully Connected
        3. 9.4.3 Determining Whether a Graph Has an Euler Circuit
        4. 9.4.4 Determining Whether a Graph Has an Euler Path
        5. 9.4.5 Graph Tools in Ruby
      5. 9.5 Conclusion
    21. Chapter 10. I/O and Data Storage
      1. 10.1 Working with Files and Directories
        1. 10.1.1 Opening and Closing Files
        2. 10.1.2 Updating a File
        3. 10.1.3 Appending to a File
        4. 10.1.4 Random Access to Files
        5. 10.1.5 Working with Binary Files
        6. 10.1.6 Locking Files
        7. 10.1.7 Performing Simple I/O
        8. 10.1.8 Performing Buffered and Unbuffered I/O
        9. 10.1.9 Manipulating File Ownership and Permissions
        10. 10.1.10 Retrieving and Setting Timestamp Information
        11. 10.1.11 Checking File Existence and Size
        12. 10.1.12 Checking Special File Characteristics
        13. 10.1.13 Working with Pipes
        14. 10.1.14 Performing Special I/O Operations
        15. 10.1.15 Using Nonblocking I/O
        16. 10.1.16 Using readpartial
        17. 10.1.17 Manipulating Pathnames
        18. 10.1.18 Using the Pathname Class
        19. 10.1.19 Command-Level File Manipulation
        20. 10.1.20 Grabbing Characters from the Keyboard
        21. 10.1.21 Reading an Entire File into Memory
        22. 10.1.22 Iterating Over a File by Lines
        23. 10.1.23 Iterating Over a File by Byte or Character
        24. 10.1.24 Treating a String As a File
        25. 10.1.25 Copying a Stream
        26. 10.1.26 Working with Character Encodings
        27. 10.1.27 Reading Data Embedded in a Program
        28. 10.1.28 Reading Program Source
        29. 10.1.29 Working with Temporary Files
        30. 10.1.30 Changing and Setting the Current Directory
        31. 10.1.31 Changing the Current Root
        32. 10.1.32 Iterating Over Directory Entries
        33. 10.1.33 Getting a List of Directory Entries
        34. 10.1.34 Creating a Chain of Directories
        35. 10.1.35 Deleting a Directory Recursively
        36. 10.1.36 Finding Files and Directories
      2. 10.2 Higher-Level Data Access
        1. 10.2.1 Simple Marshaling
        2. 10.2.2 “Deep Copying” with Marshal
        3. 10.2.3 More Complex Marshaling
        4. 10.2.4 Marshaling with YAML
        5. 10.2.5 Persisting Data with JSON
        6. 10.2.6 Working with CSV Data
        7. 10.2.7 SQLite3 for SQL Data Storage
      3. 10.3 Connecting to External Data Stores
        1. 10.3.1 Connecting to MySQL Databases
        2. 10.3.2 Connecting to PostgreSQL Databases
        3. 10.3.3 Object-Relational Mappers (ORMs)
        4. 10.3.4 Connecting to Redis Data Stores
      4. 10.4 Conclusion
    22. Chapter 11. OOP and Dynamic Features in Ruby
      1. 11.1 Everyday OOP Tasks
        1. 11.1.1 Using Multiple Constructors
        2. 11.1.2 Creating Instance Attributes
        3. 11.1.3 Using More Elaborate Constructors
        4. 11.1.4 Creating Class-Level Attributes and Methods
        5. 11.1.5 Inheriting from a Superclass
        6. 11.1.6 Testing Classes of Objects
        7. 11.1.7 Testing Equality of Objects
        8. 11.1.8 Controlling Access to Methods
        9. 11.1.9 Copying an Object
        10. 11.1.10 Using initialize_copy
        11. 11.1.11 Understanding allocate
        12. 11.1.12 Working with Modules
        13. 11.1.13 Transforming or Converting Objects
        14. 11.1.14 Creating Data-Only Classes (Structs)
        15. 11.1.15 Freezing Objects
        16. 11.1.16 Using tap in Method Chaining
      2. 11.2 More Advanced Techniques
        1. 11.2.1 Sending an Explicit Message to an Object
        2. 11.2.2 Specializing an Individual Object
        3. 11.2.3 Nesting Classes and Modules
        4. 11.2.4 Creating Parametric Classes
        5. 11.2.5 Storing Code as Proc Objects
        6. 11.2.6 Storing Code as Method Objects
        7. 11.2.7 Using Symbols as Blocks
        8. 11.2.8 How Module Inclusion Works
        9. 11.2.9 Detecting Default Parameters
        10. 11.2.10 Delegating or Forwarding
        11. 11.2.11 Defining Class-Level Readers and Writers
        12. 11.2.12 Working in Advanced Programming Disciplines
      3. 11.3 Working with Dynamic Features
        1. 11.3.1 Evaluating Code Dynamically
        2. 11.3.2 Retrieving a Constant by Name
        3. 11.3.3 Retrieving a Class by Name
        4. 11.3.4 Using define_method
        5. 11.3.5 Obtaining Lists of Defined Entities
        6. 11.3.6 Removing Definitions
        7. 11.3.7 Handling References to Nonexistent Constants
        8. 11.3.8 Handling Calls to Nonexistent Methods
        9. 11.3.9 Improved Security with taint
        10. 11.3.10 Defining Finalizers for Objects
      4. 11.4 Program Introspection
        1. 11.4.1 Traversing the Object Space
        2. 11.4.2 Examining the Call Stack
        3. 11.4.3 Tracking Changes to a Class or Object Definition
        4. 11.4.4 Monitoring Program Execution
      5. 11.5 Conclusion
    23. Chapter 12. Graphical Interfaces for Ruby
      1. 12.1 Shoes 4
        1. 12.1.1 Starting Out with Shoes
        2. 12.1.2 An Interactive Button
        3. 12.1.3 Text and Input
        4. 12.1.4 Layout
        5. 12.1.5 Images and Shapes
        6. 12.1.6 Events
        7. 12.1.7 Other Notes
      2. 12.2 Ruby/Tk
        1. 12.2.1 Overview
        2. 12.2.2 A Simple Windowed Application
        3. 12.2.3 Working with Buttons
        4. 12.2.4 Working with Text Fields
        5. 12.2.5 Working with Other Widgets
        6. 12.2.6 Other Notes
      3. 12.3 Ruby/GTK3
        1. 12.3.1 Overview
        2. 12.3.2 A Simple Windowed Application
        3. 12.3.3 Working with Buttons
        4. 12.3.4 Working with Text Fields
        5. 12.3.5 Working with Other Widgets
        6. 12.3.6 Other Notes
      4. 12.4 QtRuby
        1. 12.4.1 Overview
        2. 12.4.2 A Simple Windowed Application
        3. 12.4.3 Working with Buttons
        4. 12.4.4 Working with Text Fields
        5. 12.4.5 Working with Other Widgets
        6. 12.4.6 Other Notes
      5. 12.5 Swing
      6. 12.6 Other GUI Toolkits
        1. 12.6.1 UNIX and X11
        2. 12.6.2 FXRuby (FOX)
        3. 12.6.3 RubyMotion for iOS and Mac OS X
        4. 12.6.4 The Windows Win32API
      7. 12.7 Conclusion
    24. Chapter 13. Threads and Concurrency
      1. 13.1 Creating and Manipulating Threads
        1. 13.1.1 Creating Threads
        2. 13.1.2 Accessing Thread-Local Variables
        3. 13.1.3 Querying and Changing Thread Status
        4. 13.1.4 Achieving a Rendezvous (and Capturing a Return Value)
        5. 13.1.5 Dealing with Exceptions
        6. 13.1.6 Using a Thread Group
      2. 13.2 Synchronizing Threads
        1. 13.2.1 Performing Simple Synchronization
        2. 13.2.2 Synchronizing Access with a Mutex
        3. 13.2.3 Using the Built-in Queue Classes
        4. 13.2.4 Using Condition Variables
        5. 13.2.5 Other Synchronization Techniques
        6. 13.2.6 Setting a Timeout for an Operation
        7. 13.2.7 Waiting for an Event
        8. 13.2.8 Collection Searching in Parallel
        9. 13.2.9 Recursive Deletion in Parallel
      3. 13.3 Fibers and Cooperative Multitasking
      4. 13.4 Conclusion
    25. Chapter 14. Scripting and System Administration
      1. 14.1 Running External Programs
        1. 14.1.1 Using system and exec
        2. 14.1.2 Capturing Command Output
        3. 14.1.3 Manipulating Processes
        4. 14.1.4 Manipulating Standard Input and Output
      2. 14.2 Command-Line Options and Arguments
        1. 14.2.1 Working with ARGV
        2. 14.2.2 Working with ARGF
        3. 14.2.3 Parsing Command-Line Options
      3. 14.3 The Shell Library
        1. 14.3.1 Using Shell for I/O Redirection
        2. 14.3.2 Other Notes on Shell
      4. 14.4 Accessing Environment Variables
        1. 14.4.1 Getting and Setting Environment Variables
        2. 14.4.2 Storing Environment Variables as an Array or Hash
      5. 14.5 Working with Files, Directories, and Trees
        1. 14.5.1 A Few Words on Text Filters
        2. 14.5.2 Copying a Directory Tree
        3. 14.5.3 Deleting Files by Age or Other Criteria
        4. 14.5.4 Determining Free Space on a Disk
      6. 14.6 Other Scripting Tasks
        1. 14.6.1 Distributing Ruby Programs
        2. 14.6.2 Piping into the Ruby Interpreter
        3. 14.6.3 Testing Whether a Program Is Running Interactively
        4. 14.6.4 Determining the Current Platform or Operating System
        5. 14.6.5 Using the Etc Module
      7. 14.7 Conclusion
    26. Chapter 15. Ruby and Data Formats
      1. 15.1 Parsing JSON
        1. 15.1.1 Navigating JSON Data
        2. 15.1.2 Handling Non-JSON Data Types
        3. 15.1.3 Other JSON Libraries
      2. 15.2 Parsing XML (and HTML)
        1. 15.2.1 Document Parsing
        2. 15.2.2 Stream Parsing
      3. 15.3 Working with RSS and Atom
        1. 15.3.1 Parsing Feeds
        2. 15.3.2 Generating Feeds
      4. 15.4 Manipulating Image Data with RMagick
        1. 15.4.1 Common Graphics Tasks
        2. 15.4.2 Special Effects and Transformations
        3. 15.4.3 The Drawing API
      5. 15.5 Creating PDF Documents with Prawn
        1. 15.5.1 Basic Concepts and Techniques
        2. 15.5.2 An Example Document
      6. 15.6 Conclusion
    27. Chapter 16. Testing and Debugging
      1. 16.1 Testing with RSpec
      2. 16.2 Testing with Minitest
      3. 16.3 Testing with Cucumber
      4. 16.4 Using the byebug Debugger
      5. 16.5 Using pry for Debugging
      6. 16.6 Measuring Performance
      7. 16.7 Pretty-Printing Objects
      8. 16.8 Not Covered Here
      9. 16.9 Conclusion
    28. Chapter 17. Packaging and Distributing Code
      1. 17.1 Libraries and Rubygems
        1. 17.1.1 Using Rubygems
        2. 17.1.2 Creating Gems
      2. 17.2 Managing Dependencies with Bundler
        1. 17.2.1 Semantic Versioning
        2. 17.2.2 Dependencies from Git
        3. 17.2.3 Creating Gems with Bundler
        4. 17.2.4 Private Gems
      3. 17.3 Using RDoc
        1. 17.3.1 Simple Markup
        2. 17.3.2 Advanced Documentation with Yard
      4. 17.4 Conclusion
    29. Chapter 18. Network Programming
      1. 18.1 Network Servers
        1. 18.1.1 A Simple Server: Time of Day
        2. 18.1.2 Implementing a Threaded Server
        3. 18.1.3 Case Study: A Peer-to-Peer Chess Server
      2. 18.2 Network Clients
        1. 18.2.1 Retrieving Truly Random Numbers from the Web
        2. 18.2.2 Contacting an Official Timeserver
        3. 18.2.3 Interacting with a POP Server
        4. 18.2.4 Sending Mail with SMTP
        5. 18.2.5 Interacting with an IMAP Server
        6. 18.2.6 Encoding/Decoding Attachments
        7. 18.2.7 Case Study: A Mail-News Gateway
        8. 18.2.8 Retrieving a Web Page from a URL
        9. 18.2.9 Using the Open-URI Library
      3. 18.3 Conclusion
    30. Chapter 19. Ruby and Web Applications
      1. 19.1 HTTP Servers
        1. 19.1.1 A Simple HTTP Server
        2. 19.1.2 Rack and Web Servers
      2. 19.2 Application Frameworks
        1. 19.2.1 Routing in Sinatra
        2. 19.2.2 Routing in Rails
        3. 19.2.3 Parameters in Sinatra
        4. 19.2.4 Parameters in Rails
      3. 19.3 Storing Data
        1. 19.3.1 Databases
        2. 19.3.2 Data Stores
      4. 19.4 Generating HTML
        1. 19.4.1 ERB
        2. 19.4.2 Haml
        3. 19.4.3 Other Templating Systems
      5. 19.5 The Asset Pipeline
        1. 19.5.1 CSS and Sass
        2. 19.5.2 JavaScript and CoffeeScript
      6. 19.6 Web Services via HTTP
        1. 19.6.1 JSON for APIs
        2. 19.6.2 REST (and REST-ish) APIs
      7. 19.7 Generating Static Sites
        1. 19.7.1 Middleman
        2. 19.7.2 Other Static Site Generators
      8. 19.8 Conclusion
    31. Chapter 20. Distributed Ruby
      1. 20.1 An Overview: Using drb
      2. 20.2 Case Study: A Stock Ticker Simulation
      3. 20.3 Rinda: A Ruby Tuplespace
      4. 20.4 Service Discovery with Distributed Ruby
      5. 20.5 Conclusion
    32. Chapter 21. Ruby Development Tools
      1. 21.1 Using Rake
      2. 21.2 Using irb
      3. 21.3 The Basics of pry
      4. 21.4 The ri Utility
      5. 21.5 Editor Support
        1. 21.5.1 Vim
        2. 21.5.2 Emacs
      6. 21.6 Ruby Version Managers
        1. 21.6.1 Using rvm
        2. 21.6.2 Using rbenv
        3. 21.6.3 Using chruby
      7. 21.7 Conclusion
    33. Chapter 22. The Ruby Community
      1. 22.1 Web Resources
      2. 22.2 Mailing Lists, Podcasts, and Forums
      3. 22.3 Ruby Bug Reports and Feature Requests
      4. 22.4 IRC Channels
      5. 22.5 Ruby Conferences
      6. 22.6 Local Ruby Groups
      7. 22.7 Conclusion
    34. Index
    35. Code Snippets