Metaprogramming Ruby
Total Page:16
File Type:pdf, Size:1020Kb
What Readers Are Saying About Metaprogramming Ruby Reading this book was like diving into a new world of thinking. I tried a mix of Java and JRuby metaprogramming on a recent project. Using Java alone would now feel like entering a sword fight carrying only a banana, when my opponent is wielding a one-meter-long Samurai blade. Sebastian Hennebrüder Java Consultant and Trainer, laliluna.de This Ruby book fills a gap between language reference manuals and programming cookbooks. Not only does it explain various meta- programming facilities, but it also shows a pragmatic way of making software smaller and better. There’s a caveat, though; when the new knowledge sinks in, programming in more mainstream languages will start feeling like a chore. Jurek Husakowski Software Designer, Philips Applied Technologies Before this book, I’d never found a clear organization and explanation of concepts like the Ruby object model, closures, DSLs definition, and eigenclasses all spiced with real-life examples taken from the gems we usually use every day. This book is definitely worth reading. Carlo Pecchia Software Engineer I’ve had a lot of trouble finding a good way to pick up these meta- programming techniques, and this book is bar none the best way to do it. Paolo Perrotta makes it painless to learn Ruby’s most complex secrets and use them in practical applications. Chris Bunch Software Engineer Metaprogramming Ruby Program Like the Ruby Pros Paolo Perrotta The Pragmatic Bookshelf Raleigh, North Carolina Dallas, Texas Many of the designations used by manufacturers and sellers to distinguish their prod- ucts are claimed as trademarks. Where those designations appear in this book, and The Pragmatic Programmers, LLC was aware of a trademark claim, the designations have been printed in initial capital letters or in all capitals. The Pragmatic Starter Kit, The Pragmatic Programmer, Pragmatic Programming, Pragmatic Bookshelf and the linking g device are trademarks of The Pragmatic Programmers, LLC. Every precaution was taken in the preparation of this book. However, the publisher assumes no responsibility for errors or omissions, or for damages that may result from the use of information (including program listings) contained herein. Our Pragmatic courses, workshops, and other products can help you and your team create better software and have more fun. For more information, as well as the latest Pragmatic titles, please visit us at http://www.pragprog.com Copyright © 2010 Paolo Perrotta. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmit- ted, in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior consent of the publisher. Printed in the United States of America. ISBN-10: 1-934356-47-6 ISBN-13: 978-1-934356-47-0 Printed on acid-free paper. P1.0 printing, January 2010 Version: 2010-1-29 To Carlo. Contents Foreword 10 Acknowledgments 11 Introduction 13 The “M” Word ............................ 14 About This Book .......................... 21 About You .............................. 24 I Metaprogramming Ruby 26 1 Monday: The Object Model 27 1.1 Monday with Bill ...................... 27 1.2 Open Classes ........................ 28 1.3 The Truth About Classes .................. 33 1.4 Quiz: Missing Lines ..................... 45 1.5 What Happens When You Call a Method? . 46 1.6 Quiz: Tangle of Modules .................. 56 1.7 Object Model Wrap-Up ................... 59 2 Tuesday: Methods 60 2.1 A Duplication Problem ................... 61 2.2 Dynamic Methods ...................... 63 2.3 method_missing() ...................... 71 2.4 Quiz: Bug Hunt ....................... 82 2.5 More method_missing() ................... 84 3 Wednesday: Blocks 91 3.1 How to Handle Hump Day ................. 92 3.2 Quiz: Ruby# ......................... 93 3.3 Closures ........................... 96 3.4 instance_eval() ........................ 105 CONTENTS 8 3.5 Callable Objects ....................... 108 3.6 Writing a Domain-Specific Language ........... 116 3.7 Quiz: A Better DSL ..................... 118 4 Thursday: Class Definitions 122 4.1 Class Definitions Demystified ............... 123 4.2 Quiz: Class Taboo ...................... 130 4.3 Singleton Methods ..................... 132 4.4 Eigenclasses ......................... 137 4.5 Quiz: Module Trouble ................... 150 4.6 Aliases ............................ 152 4.7 Quiz: Broken Math ..................... 157 5 Friday: Code That Writes Code 160 5.1 Leading the Way ....................... 160 5.2 Kernel#eval ......................... 163 5.3 Quiz: Checked Attributes (Step 1) ............ 173 5.4 Quiz: Checked Attributes (Step 2) ............ 176 5.5 Quiz: Checked Attributes (Step 3) ............ 178 5.6 Quiz: Checked Attributes (Step 4) ............ 179 5.7 Hook Methods ........................ 180 5.8 Quiz: Checked Attributes (Step 5) ............ 186 6 Epilogue 188 II Metaprogramming in Rails 189 7 The Design of ActiveRecord 190 7.1 Preparing for the Tour ................... 191 7.2 The Design of ActiveRecord ................ 193 7.3 Lessons Learned ...................... 202 8 Inside ActiveRecord 206 8.1 Dynamic Attributes ..................... 206 8.2 Dynamic Finders ...................... 214 8.3 Lessons Learned ...................... 219 9 Metaprogramming Safely 224 9.1 Testing Metaprogramming ................. 224 9.2 Defusing Monkeypatches ................. 232 9.3 Lessons Learned ...................... 237 Report erratum this copy is (P1.0 printing, January 2010) CONTENTS 9 III Appendixes 239 A Common Idioms 240 A.1 Mimic Methods ....................... 240 A.2 Nil Guards .......................... 243 A.3 Tricks with Method Arguments .............. 244 A.4 Self Yield ........................... 248 A.5 Symbol#to_proc() ...................... 249 B Domain-Specific Languages 252 B.1 The Case for Domain-Specific Languages ........ 252 B.2 Internal and External DSLs ................ 254 B.3 DSLs and Metaprogramming ............... 255 C Spell Book 256 C.1 The Spells .......................... 256 D Bibliography 268 Index 269 Report erratum this copy is (P1.0 printing, January 2010) Foreword Ruby inherits characteristics from various languages — Lisp, Small- talk, C, and Perl, to name a few. Metaprogramming comes from Lisp (and Smalltalk). It’s a bit like magic, which makes something astonish- ing possible. There are two kinds of magic: white magic, which does good things, and black magic, which can do nasty things. Likewise, there are two aspects to metaprogramming. If you discipline yourself, you can do good things, such as enhancing the language without tweaking its syntax by macros or enabling internal domain-specific languages. But you can fall into the dark side of metaprogramming. Metaprogramming can confuse easily. Ruby trusts you. Ruby treats you as a grown-up programmer. It gives you great power such as metaprogramming. But you need to remember that with great power comes great responsibility. Enjoy programming in Ruby. matz October 2009 Acknowledgments Before I begin, I need to thank a few people. I’m talking to you, gen- tlemen: Joe Armstrong, Satoshi Asakawa, Paul Barry, Emmanuel Ber- nard, Roberto Bettazzoni, Ola Bini, Piergiuliano Bossi, Simone Busoli, Andrea Cisternino, Davide D’Alto, Mauro Di Nuzzo, Marco Di Timo- teo, Mauricio Fernandez, Jay Fields, Michele Finelli, Neal Ford, Flo- rian Frank, Sanne Grinovero, Federico Gobbo, Florian Groß, Sebastian Hennebrüder, Doug Hudson, Jurek Husakowski, Lyle Johnson, Luca Marchetti, MenTaLguY, Carlo Pecchia, Andrea Provaglio, Mike Roberts, Martin Rodgers, Jeremy Sydik, Andrea Tomasini, Marco Trincardi, Ivan Vaghi, Giancarlo Valente, Davide Varvello, Jim Weirich, and the dozens of readers who reported problems and errata while this book was in beta. Whether you provided reviews, quotes, fixes, opinions, or moral support, there’s at least one line in this book that changed for the bet- ter because of you. Did I say one line? For some of you, make that “a few chapters.” In particular, Ola, Satoshi, and Jurek deserve a special place on this page and my enduring gratitude. Thanks to the staff at the Pragmatic Bookshelf: Janet Furlow, Seth Maislin, Steve Peter, Susannah Davidson Pfalzer, and Kim Wimpsett. Dave and Andy, thank you for believing in this project when times got rough. Jill, thank you for making my awkward prose look so effortless. Our crunch week in Venice was a lot of hard work, but it was definitely worth it. And speaking of Venice: thank you, Lucio, for being such a dear old friend. Mom and Dad, thank you for your support, for your love, and for never asking why I was taking so long to finish this book. Most authors’ closing thanks go to their partners, and now I know why. When you’re about to finish a book, you turn back to the day when you started writing, and it feels so far away. I remember writing over lunch breaks, nights, and weekends, locked for days or weeks inside ACKNOWLEDGMENTS 12 my study, a hotel room in some foreign city, or a seashore house that would have suited a hermit. It’s such a lonesome endeavor—and yet,I never felt alone. Thank you, Mirella. Report erratum this copy is (P1.0 printing, January 2010) Will write code that writes code that writes code for food. Martin Rodgers Introduction Metaprogramming...it sounds cool! It sounds like a design technique for high-level enterprise architects or a fashionable buzzword that has found its way into press releases. In fact, far from being an abstract concept or