Effective Ruby: 48 Specific Ways to Write Better Ruby (Effective Software Development Series)
Peter J. Jones
Format: PDF / Kindle (mobi) / ePub
If you’re an experienced Ruby programmer, Effective Ruby will help you harness Ruby’s full power to write more robust, efficient, maintainable, and well-performing code. Drawing on nearly a decade of Ruby experience, Peter J. Jones brings together 48 Ruby best practices, expert tips, and shortcuts—all supported by realistic code examples.
Jones offers practical advice for each major area of Ruby development, from modules to memory to metaprogramming. Throughout, he uncovers little-known idioms, quirks, pitfalls, and intricacies that powerfully impact code behavior and performance.
Each item contains specific, actionable, clearly organized guidelines; careful advice; detailed technical arguments; and illuminating code examples. When multiple options exist, Jones shows you how to choose the one that will work best in your situation.
Effective Ruby will help you systematically improve your code—not by blindly following rules, but by thoroughly understanding Ruby programming techniques.
Key features of this concise guide include
How to avoid pitfalls associated with Ruby’s sometimes surprising idiosyncrasies
What you should know about inheritance hierarchies to successfully use Rails (and other large frameworks)
How to use misunderstood methods to do amazingly useful things with collections
Better ways to use exceptions to improve code reliability
Powerful metaprogramming approaches (and techniques to avoid)
Practical, efficient testing solutions, including MiniTest Unit and Spec Testing
How to reliably manage RubyGem dependencies
How to make the most of Ruby’s memory management and profiling tools
How to improve code efficiency by understanding the Ruby interpreter’s internals
sum + (reading.high + reading.low) / 2.0 end total / @readings.size.to_f end The existing mean method required few changes but now has a much better OOP feel to it. Accessing the high and low attributes through getter methods has a subtle side effect too. Typos in attribute names will now raise a NoMethodError exception. The same isn’t the case when using hashes. Attempting to access an invalid key in a hash doesn’t raise an exception but instead returns nil. This usually means that you’ll wind
we can use def_delegators and def_delegators_with_super to set up the method forwarding to @hash. We’ve seen def_delegators before in Item 21 and def_delegators_with_super does the exact same thing with one exception. After forwarding the original method call to the target object, the generated delegation method also calls super. Using this helper method gives RaisingHash three new instance methods: freeze, taint, and untaint. Each of which calls a corresponding method on the @hash object
than a mess of strings with interpolated variables. Back to our use of instance_exec, look what happens now if you give reset_var a bad variable name: irb> Reset.reset_var(c, "x;") NameError: `@x;' is not allowed as an instance variable name This time the code raises a NameError unlike the previous version which raised a SyntaxError. The difference of course is that the string which was passed to reset_var wasn’t evaluated as Ruby code. Instead, it was only used to look up an instance variable
subsequently marked. Next, any objects that weren’t marked in the first phase are considered garbage and are swept away, releasing their memory back to Ruby and possibly the operating system. Traversing the object graph and marking reachable objects is expensive. Ruby 2.1 introduced an optimization through a new generational garbage collector. Objects are divided into two categories, young and old. Generational garbage collectors work from the premise that most objects don’t live very long.
throughout the application need to query the request object to discover various details about the current user. If it weren’t for the memoization, each call to current_user would trigger a call to User::find, which presumably queries a database. Caching the result of an expensive method call like this can have a major impact on performance. Let’s look at another example. Consider this: def shipped? (order_id) file = fetch_confirmation_file if file status = parse_confirmation_file(file)