HAPPY BOOKSGIVING
Use code BOOKSGIVING during checkout to save 40%-55% on books and eBooks. Shop now.
Register your product to gain access to bonus material or receive a coupon.
This eBook includes the following formats, accessible from your Account page after purchase:
EPUB The open industry format known for its reflowable content and usability on supported mobile devices.
PDF The popular standard, used most often with the free Acrobat® Reader® software.
This eBook requires no passwords or activation to read. We customize your eBook by discreetly watermarking it with your name, making it uniquely yours.
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
All source code for this book may be downloaded at www.rubyhacker.com.
informit.com/aw
informit.com/ruby
rubyhacker.com/therubyway
therubyway.io
Foreword xxiv
Acknowledgments xxviii
About the Authors xxxii
Introduction xxxiii
1 Ruby in Review 1
1.1 An Introduction to Object Orientation 2
1.1.1 What Is an Object? 2
1.1.2 Inheritance 4
1.1.3 Polymorphism 6
1.1.4 A Few More Terms 7
1.2 Basic Ruby Syntax and Semantics 8
1.2.1 Keywords and Identifiers 9
1.2.2 Comments and Embedded Documentation 10
1.2.3 Constants, Variables, and Types 11
1.2.4 Operators and Precedence 13
1.2.5 A Sample Program 14
1.2.6 Looping and Branching 17
1.2.7 Exceptions 22
1.3 OOP in Ruby 25
1.3.1 Objects 26
1.3.2 Built-in Classes 26
1.3.3 Modules and Mixins 28
1.3.4 Creating Classes 29
1.3.5 Methods and Attributes 34
1.4 Dynamic Aspects of Ruby 36
1.4.1 Coding at Runtime 36
1.4.2 Reflection 38
1.4.3 Missing Methods 40
1.4.4 Garbage Collection 40
1.5 Training Your Intuition: Things to Remember 41
1.5.1 Syntax Issues 41
1.5.2 Perspectives in Programming 44
1.5.3 Ruby’s case Statement 47
1.5.4 Rubyisms and Idioms 50
1.5.5 Expression Orientation and Other Miscellaneous Issues 57
1.6 Ruby Jargon and Slang 59
1.7 Conclusion 62
2 Working with Strings 63
2.1 Representing Ordinary Strings 64
2.2 Representing Strings with Alternate Notations 65
2.3 Using Here-Documents 65
2.4 Finding the Length of a String 67
2.5 Processing a Line at a Time 68
2.6 Processing a Character or Byte at a Time 68
2.7 Performing Specialized String Comparisons 69
2.8 Tokenizing a String 71
2.9 Formatting a String 73
2.10 Using Strings as IO Objects 74
2.11 Controlling Uppercase and Lowercase 74
2.12 Accessing and Assigning Substrings 75
2.13 Substituting in Strings 78
2.14 Searching a String 79
2.15 Converting Between Characters and ASCII Codes 80
2.16 Implicit and Explicit Conversion 80
2.17 Appending an Item onto a String 83
2.18 Removing Trailing Newlines and Other Characters 83
2.19 Trimming Whitespace from a String 84
2.20 Repeating Strings 85
2.21 Embedding Expressions within Strings 85
2.22 Delayed Interpolation of Strings 86
2.23 Parsing Comma-Separated Data 86
2.24 Converting Strings to Numbers (Decimal and Otherwise) 87
2.25 Encoding and Decoding rot13 Text 89
2.26 Encrypting Strings 90
2.27 Compressing Strings 91
2.28 Counting Characters in Strings 92
2.29 Reversing a String 92
2.30 Removing Duplicate Characters 93
2.31 Removing Specific Characters 93
2.32 Printing Special Characters 93
2.33 Generating Successive Strings 94
2.34 Calculating a 32-Bit CRC 94
2.35 Calculating the SHA-256 Hash of a String 95
2.36 Calculating the Levenshtein Distance Between Two Strings 96
2.37 Encoding and Decoding Base64 Strings 98
2.38 Expanding and Compressing Tab Characters 98
2.39 Wrapping Lines of Text 99
2.40 Conclusion 100
3 Working with Regular Expressions 101
3.1 Regular Expression Syntax 102
3.2 Compiling Regular Expressions 104
3.3 Escaping Special Characters 105
3.4 Using Anchors 105
3.5 Using Quantifiers 106
3.6 Positive and Negative Lookahead 109
3.7 Positive and Negative Lookbehind 110
3.8 Accessing Backreferences 111
3.9 Named Matches 114
3.10 Using Character Classes 116
3.11 Extended Regular Expressions 118
3.12 Matching a Newline with a Dot 119
3.13 Using Embedded Options 119
3.14 Using Embedded Subexpressions 120
3.14.1 Recursion in Regular Expressions 121
3.15 A Few Sample Regular Expressions 122
3.15.1 Matching an IP Address 122
3.15.2 Matching a Keyword-Value Pair 123
3.15.3 Matching Roman Numerals 124
3.15.4 Matching Numeric Constants 125
3.15.5 Matching a Date/Time String 125
3.15.6 Detecting Doubled Words in Text 126
3.15.7 Matching All-Caps Words 127
3.15.8 Matching Version Numbers 127
3.15.9 A Few Other Patterns 127
3.16 Conclusion 128
4 Internationalization in Ruby 129
4.1 Background and Terminology 131
4.2 Working with Character Encodings 135
4.2.1 Normalization 136
4.2.2 Encoding Conversions 139
4.2.3 Transliteration 141
4.2.4 Collation 141
4.3 Translations 144
4.3.1 Defaults 146
4.3.2 Namespaces 147
4.3.3 Interpolation 148
4.3.4 Pluralization 149
4.4 Localized Formatting 151
4.4.1 Dates and Times 151
4.4.2 Numbers 152
4.4.3 Currencies 153
4.5 Conclusion 153
5 Performing Numerical Calculations 155
5.1 Representing Numbers in Ruby 156
5.2 Basic Operations on Numbers 157
5.3 Rounding Floating Point Values 158
5.4 Comparing Floating Point Numbers 160
5.5 Formatting Numbers for Output 162
5.6 Formatting Numbers with Commas 162
5.7 Working with Very Large Integers 163
5.8 Using BigDecimal 163
5.9 Working with Rational Values 166
5.10 Matrix Manipulation 167
5.11 Working with Complex Numbers 171
5.12 Using mathn 172
5.13 Finding Prime Factorization, GCD, and LCM 173
5.14 Working with Prime Numbers 174
5.15 Implicit and Explicit Numeric Conversion 175
5.16 Coercing Numeric Values 176
5.17 Performing Bit-Level Operations on Numbers 177
5.18 Performing Base Conversions 179
5.19 Finding Cube Roots, Fourth Roots, and So On 180
5.20 Determining the Architecture’s Byte Order 181
5.21 Numerical Computation of a Definite Integral 182
5.22 Trigonometry in Degrees, Radians, and Grads 183
5.23 Finding Logarithms with Arbitrary Bases 184
5.24 Finding the Mean, Median, and Mode of a Data Set 185
5.25 Variance and Standard Deviation 187
5.26 Finding a Correlation Coefficient 187
5.27 Generating Random Numbers 189
5.28 Caching Functions with Memoization 190
5.29 Conclusion 191
6 Symbols and Ranges 193
6.1 Symbols 193
6.1.1 Symbols as Enumerations 195
6.1.2 Symbols as Metavalues 196
6.1.3 Symbols, Variables, and Methods 197
6.1.4 Converting to/from Symbols 197
6.2 Ranges 199
6.2.1 Open and Closed Ranges 199
6.2.2 Finding Endpoints 200
6.2.3 Iterating Over Ranges 200
6.2.4 Testing Range Membership 201
6.2.5 Converting to Arrays 202
6.2.6 Backward Ranges 202
6.2.7 The Flip-Flop Operator 203
6.2.8 Custom Ranges 206
6.3 Conclusion 209
7 Working with Times and Dates 211
7.1 Determining the Current Time 212
7.2 Working with Specific Times (Post-Epoch) 212
7.3 Determining the Day of the Week 214
7.4 Determining the Date of Easter 215
7.5 Finding the Nth Weekday in a Month 215
7.6 Converting Between Seconds and Larger Units 217
7.7 Converting to and from the Epoch 217
7.8 Working with Leap Seconds: Don’t! 218
7.9 Finding the Day of the Year 219
7.10 Validating a Date or Time 219
7.11 Finding the Week of the Year 220
7.12 Detecting Leap Years 221
7.13 Obtaining the Time Zone 222
7.14 Working with Hours and Minutes Only 222
7.15 Comparing Time Values 223
7.16 Adding Intervals to Time Values 223
7.17 Computing the Difference in Two Time Values 224
7.18 Working with Specific Dates (Pre-Epoch) 224
7.19 Time, Date, and DateTime 225
7.20 Parsing a Date or Time String 225
7.21 Formatting and Printing Time Values 226
7.22 Time Zone Conversions 227
7.23 Determining the Number of Days in a Month 228
7.24 Dividing a Month into Weeks 229
7.25 Conclusion 230
8 Arrays, Hashes, and Other Enumerables 231
8.1 Working with Arrays 232
8.1.1 Creating and Initializing an Array 232
8.1.2 Accessing and Assigning Array Elements 233
8.1.3 Finding an Array’s Size 235
8.1.4 Comparing Arrays 235
8.1.5 Sorting an Array 237
8.1.6 Selecting from an Array by Criteria 240
8.1.7 Using Specialized Indexing Functions 242
8.1.8 Implementing a Sparse Matrix 244
8.1.9 Using Arrays as Mathematical Sets 244
8.1.10 Randomizing an Array 248
8.1.11 Using Multidimensional Arrays 249
8.1.12 Finding Elements in One Array But Not Another 250
8.1.13 Transforming or Mapping Arrays 250
8.1.14 Removing nil Values from an Array 251
8.1.15 Removing Specific Array Elements 251
8.1.16 Concatenating and Appending onto Arrays 253
8.1.17 Using an Array as a Stack or Queue 254
8.1.18 Iterating over an Array 254
8.1.19 Interposing Delimiters to Form a String 255
8.1.20 Reversing an Array 256
8.1.21 Removing Duplicate Elements from an Array 256
8.1.22 Interleaving Arrays 256
8.1.23 Counting Frequency of Values in an Array 257
8.1.24 Inverting an Array to Form a Hash 257
8.1.25 Synchronized Sorting of Multiple Arrays 258
8.1.26 Establishing a Default Value for New Array Elements 259
8.2 Working with Hashes 260
8.2.1 Creating a New Hash 260
8.2.2 Specifying a Default Value for a Hash 261
8.2.3 Accessing and Adding Key-Value Pairs 262
8.2.4 Deleting Key-Value Pairs 264
8.2.5 Iterating Over a Hash 264
8.2.6 Inverting a Hash 265
8.2.7 Detecting Keys and Values in a Hash 265
8.2.8 Extracting Hashes into Arrays 266
8.2.9 Selecting Key-Value Pairs by Criteria 266
8.2.10 Sorting a Hash 267
8.2.11 Merging Two Hashes 268
8.2.12 Creating a Hash from an Array 268
8.2.13 Finding Difference or Intersection of Hash Keys 268
8.2.14 Using a Hash as a Sparse Matrix 269
8.2.15 Implementing a Hash with Duplicate Keys 270
8.2.16 Other Hash Operations 273
8.3 Enumerables in General 273
8.3.1 The inject Method 274
8.3.2 Using Quantifiers 275
8.3.3 The partition Method 276
8.3.4 Iterating by Groups 277
8.3.5 Converting to Arrays or Sets 278
8.3.6 Using Enumerator Objects 278
8.4 More on Enumerables 280
8.4.1 Searching and Selecting 280
8.4.2 Counting and Comparing 281
8.4.3 Iterating 282
8.4.4 Extracting and Converting 283
8.4.5 Lazy Enumerators 284
8.5 Conclusion 285
9 More Advanced Data Structures 287
9.1 Working with Sets 288
9.1.1 Simple Set Operations 288
9.1.2 More Advanced Set Operations 290
9.2 Working with Stacks and Queues 291
9.2.1 Implementing a Stricter Stack 293
9.2.2 Detecting Unbalanced Punctuation in Expressions 294
9.2.3 Understanding Stacks and Recursion 295
9.2.4 Implementing a Stricter Queue 297
9.3 Working with Trees 298
9.3.1 Implementing a Binary Tree 298
9.3.2 Sorting Using a Binary Tree 300
9.3.3 Using a Binary Tree as a Lookup Table 302
9.3.4 Converting a Tree to a String or Array 303
9.4 Working with Graphs 304
9.4.1 Implementing a Graph as an Adjacency Matrix 304
9.4.2 Determining Whether a Graph Is Fully Connected 307
9.4.3 Determining Whether a Graph Has an Euler Circuit 308
9.4.4 Determining Whether a Graph Has an Euler Path 309
9.4.5 Graph Tools in Ruby 310
9.5 Conclusion 310
10 I/O and Data Storage 311
10.1 Working with Files and Directories 313
10.1.1 Opening and Closing Files 313
10.1.2 Updating a File 314
10.1.3 Appending to a File 315
10.1.4 Random Access to Files 315
10.1.5 Working with Binary Files 316
10.1.6 Locking Files 318
10.1.7 Performing Simple I/O 318
10.1.8 Performing Buffered and Unbuffered I/O 320
10.1.9 Manipulating File Ownership and Permissions 321
10.1.10 Retrieving and Setting Timestamp Information 323
10.1.11 Checking File Existence and Size 325
10.1.12 Checking Special File Characteristics 326
10.1.13 Working with Pipes 328
10.1.14 Performing Special I/O Operations 329
10.1.15 Using Nonblocking I/O 330
10.1.16 Using readpartial 331
10.1.17 Manipulating Pathnames 331
10.1.18 Using the Pathname Class 333
10.1.19 Command-Level File Manipulation 334
10.1.20 Grabbing Characters from the Keyboard 336
10.1.21 Reading an Entire File into Memory 336
10.1.22 Iterating Over a File by Lines 337
10.1.23 Iterating Over a File by Byte or Character 337
10.1.24 Treating a String As a File 338
10.1.25 Copying a Stream 339
10.1.26 Working with Character Encodings 339
10.1.27 Reading Data Embedded in a Program 339
10.1.28 Reading Program Source 340
10.1.29 Working with Temporary Files 340
10.1.30 Changing and Setting the Current Directory 341
10.1.31 Changing the Current Root 342
10.1.32 Iterating Over Directory Entries 342
10.1.33 Getting a List of Directory Entries 342
10.1.34 Creating a Chain of Directories 342
10.1.35 Deleting a Directory Recursively 343
10.1.36 Finding Files and Directories 343
10.2 Higher-Level Data Access 344
10.2.1 Simple Marshaling 345
10.2.2 “Deep Copying” with Marshal 346
10.2.3 More Complex Marshaling 346
10.2.4 Marshaling with YAML 347
10.2.5 Persisting Data with JSON 349
10.2.6 Working with CSV Data 350
10.2.7 SQLite3 for SQL Data Storage 352
10.3 Connecting to External Data Stores 353
10.3.1 Connecting to MySQL Databases 354
10.3.2 Connecting to PostgreSQL Databases 356
10.3.3 Object-Relational Mappers (ORMs) 358
10.3.4 Connecting to Redis Data Stores 359
10.4 Conclusion 360
11 OOP and Dynamic Features in Ruby 361
11.1 Everyday OOP Tasks 362
11.1.1 Using Multiple Constructors 362
11.1.2 Creating Instance Attributes 364
11.1.3 Using More Elaborate Constructors 366
11.1.4 Creating Class-Level Attributes and Methods 368
11.1.5 Inheriting from a Superclass 372
11.1.6 Testing Classes of Objects 374
11.1.7 Testing Equality of Objects 377
11.1.8 Controlling Access to Methods 378
11.1.9 Copying an Object 381
11.1.10 Using initialize_copy 383
11.1.11 Understanding allocate 384
11.1.12 Working with Modules 384
11.1.13 Transforming or Converting Objects 388
11.1.14 Creating Data-Only Classes (Structs) 390
11.1.15 Freezing Objects 391
11.1.16 Using tap in Method Chaining 393
11.2 More Advanced Techniques 394
11.2.1 Sending an Explicit Message to an Object 394
11.2.2 Specializing an Individual Object 396
11.2.3 Nesting Classes and Modules 399
11.2.4 Creating Parametric Classes 400
11.2.5 Storing Code as Proc Objects 403
11.2.6 Storing Code as Method Objects 405
11.2.7 Using Symbols as Blocks 406
11.2.8 How Module Inclusion Works 406
11.2.9 Detecting Default Parameters 409
11.2.10 Delegating or Forwarding 409
11.2.11 Defining Class-Level Readers and Writers 412
11.2.12 Working in Advanced Programming Disciplines 414
11.3 Working with Dynamic Features 416
11.3.1 Evaluating Code Dynamically 416
11.3.2 Retrieving a Constant by Name 418
11.3.3 Retrieving a Class by Name 418
11.3.4 Using define_method 419
11.3.5 Obtaining Lists of Defined Entities 423
11.3.6 Removing Definitions 425
11.3.7 Handling References to Nonexistent Constants 427
11.3.8 Handling Calls to Nonexistent Methods 429
11.3.9 Improved Security with taint 430
11.3.10 Defining Finalizers for Objects 432
11.4 Program Introspection 433
11.4.1 Traversing the Object Space 434
11.4.2 Examining the Call Stack 435
11.4.3 Tracking Changes to a Class or Object Definition 435
11.4.4 Monitoring Program Execution 439
11.5 Conclusion 441
12 Graphical Interfaces for Ruby 443
12.1 Shoes 4 444
12.1.1 Starting Out with Shoes 444
12.1.2 An Interactive Button 445
12.1.3 Text and Input 446
12.1.4 Layout 448
12.1.5 Images and Shapes 450
12.1.6 Events 450
12.1.7 Other Notes 451
12.2 Ruby/Tk 452
12.2.1 Overview 452
12.2.2 A Simple Windowed Application 453
12.2.3 Working with Buttons 455
12.2.4 Working with Text Fields 459
12.2.5 Working with Other Widgets 463
12.2.6 Other Notes 467
12.3 Ruby/GTK3 467
12.3.1 Overview 467
12.3.2 A Simple Windowed Application 468
12.3.3 Working with Buttons 469
12.3.4 Working with Text Fields 471
12.3.5 Working with Other Widgets 474
12.3.6 Other Notes 479
12.4 QtRuby 480
12.4.1 Overview 480
12.4.2 A Simple Windowed Application 480
12.4.3 Working with Buttons 481
12.4.4 Working with Text Fields 483
12.4.5 Working with Other Widgets 485
12.4.6 Other Notes 490
12.5 Swing 491
12.6 Other GUI Toolkits 493
12.6.1 UNIX and X11 493
12.6.2 FXRuby (FOX) 493
12.6.3 RubyMotion for iOS and Mac OS X 494
12.6.4 The Windows Win32API 494
12.7 Conclusion 494
13 Threads and Concurrency 495
13.1 Creating and Manipulating Threads 497
13.1.1 Creating Threads 497
13.1.2 Accessing Thread-Local Variables 498
13.1.3 Querying and Changing Thread Status 500
13.1.4 Achieving a Rendezvous (and Capturing a Return Value) 505
13.1.5 Dealing with Exceptions 506
13.1.6 Using a Thread Group 508
13.2 Synchronizing Threads 509
13.2.1 Performing Simple Synchronization 511
13.2.2 Synchronizing Access with a Mutex 512
13.2.3 Using the Built-in Queue Classes 515
13.2.4 Using Condition Variables 517
13.2.5 Other Synchronization Techniques 518
13.2.6 Setting a Timeout for an Operation 522
13.2.7 Waiting for an Event 524
13.2.8 Collection Searching in Parallel 525
13.2.9 Recursive Deletion in Parallel 526
13.3 Fibers and Cooperative Multitasking 527
13.4 Conclusion 530
14 Scripting and System Administration 531
14.1 Running External Programs 532
14.1.1 Using system and exec 532
14.1.2 Capturing Command Output 533
14.1.3 Manipulating Processes 534
14.1.4 Manipulating Standard Input and Output 537
14.2 Command-Line Options and Arguments 538
14.2.1 Working with ARGV 538
14.2.2 Working with ARGF 539
14.2.3 Parsing Command-Line Options 540
14.3 The Shell Library 542
14.3.1 Using Shell for I/O Redirection 542
14.3.2 Other Notes on Shell 544
14.4 Accessing Environment Variables 545
14.4.1 Getting and Setting Environment Variables 545
14.4.2 Storing Environment Variables as an Array or Hash 546
14.5 Working with Files, Directories, and Trees 547
14.5.1 A Few Words on Text Filters 547
14.5.2 Copying a Directory Tree 548
14.5.3 Deleting Files by Age or Other Criteria 549
14.5.4 Determining Free Space on a Disk 550
14.6 Other Scripting Tasks 551
14.6.1 Distributing Ruby Programs 551
14.6.2 Piping into the Ruby Interpreter 552
14.6.3 Testing Whether a Program Is Running Interactively 553
14.6.4 Determining the Current Platform or Operating System 554
14.6.5 Using the Etc Module 554
14.7 Conclusion 555
15 Ruby and Data Formats 557
15.1 Parsing JSON 558
15.1.1 Navigating JSON Data 559
15.1.2 Handling Non-JSON Data Types 560
15.1.3 Other JSON Libraries 560
15.2 Parsing XML (and HTML) 561
15.2.1 Document Parsing 561
15.2.2 Stream Parsing 564
15.3 Working with RSS and Atom 566
15.3.1 Parsing Feeds 567
15.3.2 Generating Feeds 568
15.4 Manipulating Image Data with RMagick 569
15.4.1 Common Graphics Tasks 570
15.4.2 Special Effects and Transformations 573
15.4.3 The Drawing API 576
15.5 Creating PDF Documents with Prawn 579
15.5.1 Basic Concepts and Techniques 579
15.5.2 An Example Document 580
15.6 Conclusion 584
16 Testing and Debugging 585
16.1 Testing with RSpec 586
16.2 Testing with Minitest 589
16.3 Testing with Cucumber 594
16.4 Using the byebug Debugger 596
16.5 Using pry for Debugging 600
16.6 Measuring Performance 601
16.7 Pretty-Printing Objects 606
16.8 Not Covered Here 608
16.9 Conclusion 609
17 Packaging and Distributing Code 611
17.1 Libraries and Rubygems 612
17.1.1 Using Rubygems 612
17.1.2 Creating Gems 613
17.2 Managing Dependencies with Bundler 614
17.2.1 Semantic Versioning 615
17.2.2 Dependencies from Git 616
17.2.3 Creating Gems with Bundler 617
17.2.4 Private Gems 617
17.3 Using RDoc 618
17.3.1 Simple Markup 620
17.3.2 Advanced Documentation with Yard 622
17.4 Conclusion 623
18 Network Programming 625
18.1 Network Servers 627
18.1.1 A Simple Server: Time of Day 627
18.1.2 Implementing a Threaded Server 629
18.1.3 Case Study: A Peer-to-Peer Chess Server 630
18.2 Network Clients 638
18.2.1 Retrieving Truly Random Numbers from the Web 638
18.2.2 Contacting an Official Timeserver 641
18.2.3 Interacting with a POP Server 642
18.2.4 Sending Mail with SMTP 644
18.2.5 Interacting with an IMAP Server 647
18.2.6 Encoding/Decoding Attachments 649
18.2.7 Case Study: A Mail-News Gateway 651
18.2.8 Retrieving a Web Page from a URL 657
18.2.9 Using the Open-URI Library 658
18.3 Conclusion 658
19 Ruby and Web Applications 661
19.1 HTTP Servers 662
19.1.1 A Simple HTTP Server 662
19.1.2 Rack and Web Servers 664
19.2 Application Frameworks 667
19.2.1 Routing in Sinatra 668
19.2.2 Routing in Rails 669
19.2.3 Parameters in Sinatra 671
19.2.4 Parameters in Rails 672
19.3 Storing Data 673
19.3.1 Databases 674
19.3.2 Data Stores 676
19.4 Generating HTML 677
19.4.1 ERB 678
19.4.2 Haml 680
19.4.3 Other Templating Systems 681
19.5 The Asset Pipeline 681
19.5.1 CSS and Sass 682
19.5.2 JavaScript and CoffeeScript 683
19.6 Web Services via HTTP 686
19.6.1 JSON for APIs 686
19.6.2 REST (and REST-ish) APIs 687
19.7 Generating Static Sites 688
19.7.1 Middleman 688
19.7.2 Other Static Site Generators 690
19.8 Conclusion 690
20 Distributed Ruby 691
20.1 An Overview: Using drb 692
20.2 Case Study: A Stock Ticker Simulation 695
20.3 Rinda: A Ruby Tuplespace 698
20.4 Service Discovery with Distributed Ruby 703
20.5 Conclusion 704
21 Ruby Development Tools 705
21.1 Using Rake 706
21.2 Using irb 710
21.3 The Basics of pry 715
21.4 The ri Utility 716
21.5 Editor Support 717
21.5.1 Vim 717
21.5.2 Emacs 718
21.6 Ruby Version Managers 719
21.6.1 Using rvm 719
21.6.2 Using rbenv 720
21.6.3 Using chruby 721
21.7 Conclusion 722
22 The Ruby Community 723
22.1 Web Resources 723
22.2 Mailing Lists, Podcasts, and Forums 724
22.3 Ruby Bug Reports and Feature Requests 724
22.4 IRC Channels 725
22.5 Ruby Conferences 725
22.6 Local Ruby Groups 726
22.7 Conclusion 726
Index 727