SKIP THE SHIPPING
Use code NOSHIP during checkout to save 40% on eligible eBooks, now through January 5. 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
Please visit the author's site here.
Please visit the website associated with The Ruby Way: The: Solutions and Techniques in Ruby Programming at here.
Download the sample pages (includes Chapter 2 and Index)
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 B