Cover image for Ruby Best Practices

Book description

How do you write truly elegant code with Ruby? Ruby Best Practices is for programmers who want to use Ruby as experienced Rubyists do. Written by the developer of the Ruby project Prawn, this concise book explains how to design beautiful APIs and domain-specific languages with Ruby, as well as how to work with functional programming ideas and techniques that can simplify your code and make you more productive. You'll learn how to write code that's readable, expressive, and much more. Ruby Best Practices will help you:

  • Understand the secret powers unlocked by Ruby's code blocks

  • Learn how to bend Ruby code without breaking it, such as mixing in modules on the fly

  • Discover the ins and outs of testing and debugging, and how to design for testability

  • Learn to write faster code by keeping things simple

  • Develop strategies for text processing and file management, including regular expressions

  • Understand how and why things can go wrong

  • Reduce cultural barriers by leveraging Ruby's multilingual capabilities

This book also offers you comprehensive chapters on driving code through tests, designing APIs, and project maintenance. Learn how to make the most of this rich, beautiful language with Ruby Best Practices.

Table of Contents

  1. Special Upgrade Offer
  2. Foreword
  3. Preface
    1. Audience
    2. About This Book
    3. Conventions Used in This Book
    4. Using Code Examples
    5. Safari® Books Online
    6. How to Contact Us
    7. Acknowledgments
  4. 1. Driving Code Through Tests
    1. A Quick Note on Testing Frameworks
    2. Designing for Testability
    3. Testing Fundamentals
      1. Well-Focused Examples
      2. Testing Exceptions
      3. Run the Whole Suite at Once
    4. Advanced Testing Techniques
      1. Using Mocks and Stubs
      2. Testing Complex Output
    5. Keeping Things Organized
      1. Embedding Tests in Library Files
      2. Test Helpers
      3. Custom Assertions
    6. Conclusions
  5. 2. Designing Beautiful APIs
    1. Designing for Convenience: Ruport’s Table() feature
    2. Ruby’s Secret Power: Flexible Argument Processing
      1. Standard Ordinal Arguments
      2. Ordinal Arguments with Optional Parameters
      3. Pseudo-Keyword Arguments
      4. Treating Arguments As an Array
    3. Ruby’s Other Secret Power: Code Blocks
      1. Working with Enumerable
      2. Using Blocks to Abstract Pre- and Postprocessing
      3. Blocks As Dynamic Callbacks
      4. Blocks for Interface Simplification
    4. Avoiding Surprises
      1. Use attr_reader, attr_writer, and attr_accessor
      2. Understand What method? and method! Mean
        1. Question marks
        2. Exclamation points
      3. Make Use of Custom Operators
    5. Conclusions
  6. 3. Mastering the Dynamic Toolkit
    1. BlankSlate: A BasicObject on Steroids
    2. Building Flexible Interfaces
      1. Making instance_eval() Optional
      2. Handling Messages with method_missing() and send()
      3. Dual-Purpose Accessors
    3. Implementing Per-Object Behavior
    4. Extending and Modifying Preexisting Code
      1. Adding New Functionality
      2. Modification via Aliasing
      3. Per-Object Modification
    5. Building Classes and Modules Programmatically
    6. Registering Hooks and Callbacks
      1. Detecting Newly Added Functionality
      2. Tracking Inheritance
      3. Tracking Mixins
    7. Conclusions
  7. 4. Text Processing and File Management
    1. Line-Based File Processing with State Tracking
    2. Regular Expressions
      1. Don’t Work Too Hard
      2. Anchors Are Your Friends
      3. Use Caution When Working with Quantifiers
    3. Working with Files
      1. Using Pathname and FileUtils
    4. The tempfile Standard Library
      1. Automatic Temporary Directory Handling
      2. Collision Avoidance
      3. Same Old I/O Operations
      4. Automatic Unlinking
    5. Text-Processing Strategies
      1. Advanced Line Processing
        1. Using Enumerator
        2. Tracking line numbers
      2. Atomic Saves
    6. Conclusions
  8. 5. Functional Programming Techniques
    1. Laziness Can Be a Virtue (A Look at lazy.rb)
    2. Minimizing Mutable State and Reducing Side Effects
    3. Modular Code Organization
    4. Memoization
    5. Infinite Lists
    6. Higher-Order Procedures
    7. Conclusions
  9. 6. When Things Go Wrong
    1. A Process for Debugging Ruby Code
    2. Capturing the Essence of a Defect
    3. Scrutinizing Your Code
      1. Utilizing Reflection
      2. Improving inspect Output
      3. Finding Needles in a Haystack
    4. Working with Logger
    5. Conclusions
  10. 7. Reducing Cultural Barriers
    1. m17n by Example: A Look at Ruby’s CSV Standard Library
    2. Portable m17n Through UTF-8 Transcoding
      1. Source Encodings
      2. Working with Files
      3. Transcoding User Input in an Organized Fashion
    3. m17n in Standalone Scripts
      1. Inferring Encodings from Locale
      2. Customizing Encoding Defaults
    4. m17n-Safe Low-Level Text Processing
    5. Localizing Your Code
    6. Conclusions
  11. 8. Skillful Project Maintenance
    1. Exploring a Well-Organized Ruby Project (Haml)
    2. Conventions to Know About
      1. What Goes in a README
      2. Laying Out Your Library
      3. Executables
      4. Tests
      5. Examples
    3. API Documentation via RDoc
      1. Basic Documentation Techniques and Guidelines
      2. Controlling Output with RDoc Directives
    4. The RubyGems Package Manager
      1. Writing a Gem::Specification
      2. Working with Dependencies
    5. Rake: Ruby’s Built-in Build Utility
    6. Conclusions
  12. A. Writing Backward-Compatible Code
    1. Avoiding a Mess
      1. Selective Backporting
      2. Version-Specific Code Blocks
      3. Compatibility Shims for Common Operations
    2. Nonportable Features in Ruby 1.9
      1. Pseudo-Keyword Hash Syntax
      2. Multisplat Arguments
      3. Block-Local Variables
      4. Block Arguments
      5. New Proc Syntax
      6. Oniguruma
      7. Most m17n Functionality
    3. Workarounds for Common Issues
      1. Using Enumerator
      2. String Iterators
      3. Character Operations
      4. Encoding Conversions
    4. Conclusions
  13. B. Leveraging Ruby’s Standard Library
    1. Why Do We Need a Standard Library?
    2. Pretty-Printer for Ruby Objects (pp)
    3. Working with HTTP and FTP (open-uri)
    4. Working with Dates and Times (date)
    5. Lexical Parsing with Regular Expressions (strscan)
    6. Cryptographic Hash Functions (digest)
    7. Mathematical Ruby Scripts (mathn)
    8. Working with Tabular Data (csv)
    9. Transactional Filesystem-Based Data Storage (pstore)
    10. Human-Readable Data Serialization (json)
    11. Embedded Ruby for Code Generation (erb)
    12. Conclusions
  14. C. Ruby Worst Practices
    1. Not-So-Intelligent Design
      1. Class Variables Considered Harmful
      2. Hardcoding Yourself Into a Corner
      3. When Inheritance Becomes Restrictive
    2. The Downside of Cleverness
      1. The Evils of eval()
      2. Blind Rescue Missions
      3. Doing method_missing Wrong
    3. Conclusions
  15. Index
  16. About the Author
  17. Colophon
  18. Special Upgrade Offer
  19. Copyright