SlideShare a Scribd company logo
Agile Web Development With Rails Third Edition
Third Ruby Sam download
https://ebookbell.com/product/agile-web-development-with-rails-
third-edition-third-ruby-sam-55258644
Explore and download more ebooks at ebookbell.com
Here are some recommended products that we believe you will be
interested in. You can click the link to download.
Agile Web Development With Rails 7 2nd Edition Sam Ruby Dave Thomas
https://ebookbell.com/product/agile-web-development-with-rails-7-2nd-
edition-sam-ruby-dave-thomas-51380742
Agile Web Development With Rails A Pragmatic Guide Pragmatic
Programmers 1st Edition Dave Thomas
https://ebookbell.com/product/agile-web-development-with-rails-a-
pragmatic-guide-pragmatic-programmers-1st-edition-dave-thomas-55258848
Agile Web Development With Rails 4th Edition Beta 10 Version Fourth
Edition Sam Ruby
https://ebookbell.com/product/agile-web-development-with-rails-4th-
edition-beta-10-version-fourth-edition-sam-ruby-2031134
Agile Web Development With Rails 6 Dave Thomas David B Copeland Sam
Ruby
https://ebookbell.com/product/agile-web-development-with-rails-6-dave-
thomas-david-b-copeland-sam-ruby-42203806
Agile Web Development With Rails 4 For Lorinda Hartzler Sam Ruby
https://ebookbell.com/product/agile-web-development-with-rails-4-for-
lorinda-hartzler-sam-ruby-43141470
Agile Web Development With Rails 5 1st Edition Sam Ruby
https://ebookbell.com/product/agile-web-development-with-rails-5-1st-
edition-sam-ruby-5557564
Agile Web Development With Rails 51 1st Edition Sam Ruby David B
Copeland
https://ebookbell.com/product/agile-web-development-with-rails-51-1st-
edition-sam-ruby-david-b-copeland-7037920
Agile Web Development With Rails A Pragmatic Guide Second Edition Dave
Thomas
https://ebookbell.com/product/agile-web-development-with-rails-a-
pragmatic-guide-second-edition-dave-thomas-931576
Agile Web Development With Rails 6 Dave Thomas David B Copeland Sam
Ruby
https://ebookbell.com/product/agile-web-development-with-rails-6-dave-
thomas-david-b-copeland-sam-ruby-42279272
Agile Web Development With Rails Third Edition Third Ruby Sam
Agile Web Development With Rails Third Edition Third Ruby Sam
Important Information
About Rails Versions
This book is written for Rails 2. As this book is going to press, the current
generally available gem version of Rails is 2.2.2. The code in this book has
been tested against this version.
The Rails core team is continuing to work on Rails. From time to time, new
releases may introduce incompatibilities for applications written for prior
versions of Rails, including the code in this book. Sam Ruby is tracking the
changes in Rails that affect this book on our wiki at
http://pragprog.wikidot.com/changes-to-rails
If you’re running a later version of Rails, check out the wiki pages to see if
any changes are needed to our code.
To determine the version of Rails that you are running, you can issue rails -v
at a command prompt.
Sam, Dave, and David
Agile Web Development with Rails
Third Edition
Sam Ruby
Dave Thomas
David Heinemeier Hansson
with Leon Breedt
Mike Clark
James Duncan Davidson
Justin Gehtland
Andreas Schwarz
The Pragmatic Bookshelf
Raleigh, North Carolina Dallas, Texas
Many of the designations used by manufacturers and sellers to distinguish their products are
claimed as trademarks. Where those designations appear in this book, and The Pragmatic Program-
mers, 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 Program-
ming, 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 © 2009 The Pragmatic Programmers LLC.
All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted, 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-16-6
ISBN-13: 978-1-9343561-6-6
Printed on acid-free paper.
P1.0 printing, March 2009
Version: 2009-3-19
Contents
Preface to the Second Edition 11
Preface to the Third Edition 13
1 Introduction 14
1.1 Rails Is Agile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.2 Finding Your Way Around . . . . . . . . . . . . . . . . . . . . . 17
1.3 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Part I—Getting Started 21
2 The Architecture of Rails Applications 22
2.1 Models, Views, and Controllers . . . . . . . . . . . . . . . . . . 22
2.2 Active Record: Rails Model Support . . . . . . . . . . . . . . . . 25
2.3 Action Pack: The View and Controller . . . . . . . . . . . . . . . 29
3 Installing Rails 31
3.1 Your Shopping List . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.2 Installing on Windows . . . . . . . . . . . . . . . . . . . . . . . . 31
3.3 Installing on Mac OS X . . . . . . . . . . . . . . . . . . . . . . . 33
3.4 Installing on Linux . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.5 Choosing a Rails Version . . . . . . . . . . . . . . . . . . . . . . 36
3.6 Development Environments . . . . . . . . . . . . . . . . . . . . 36
3.7 Rails and Databases . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.8 Keeping Up-to-Date . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.9 Rails and ISPs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4 Instant Gratification 44
4.1 Creating a New Application . . . . . . . . . . . . . . . . . . . . . 44
4.2 Hello, Rails! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.3 Linking Pages Together . . . . . . . . . . . . . . . . . . . . . . . 57
4.4 What We Just Did . . . . . . . . . . . . . . . . . . . . . . . . . . 61
CONTENTS 6
Part II—Building an Application 62
5 The Depot Application 63
5.1 Incremental Development . . . . . . . . . . . . . . . . . . . . . . 63
5.2 What Depot Does . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
5.3 Let’s Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
6 Task A: Product Maintenance 69
6.1 Iteration A1: Getting Something Running . . . . . . . . . . . . 69
6.2 Creating the Products Model and Maintenance Application . . 75
6.3 Iteration A2: Adding a Missing Column . . . . . . . . . . . . . . 79
6.4 Iteration A3: Validating! . . . . . . . . . . . . . . . . . . . . . . . 85
6.5 Iteration A4: Making Prettier Listings . . . . . . . . . . . . . . . 89
7 Task B: Catalog Display 95
7.1 Iteration B1: Creating the Catalog Listing . . . . . . . . . . . . 95
7.2 Iteration B2: Adding a Page Layout . . . . . . . . . . . . . . . . 99
7.3 Iteration B3: Using a Helper to Format the Price . . . . . . . . 101
7.4 Iteration B4: Linking to the Cart . . . . . . . . . . . . . . . . . . 102
8 Task C: Cart Creation 105
8.1 Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
8.2 Iteration C1: Creating a Cart . . . . . . . . . . . . . . . . . . . . 109
8.3 Iteration C2: Creating a Smarter Cart . . . . . . . . . . . . . . 112
8.4 Iteration C3: Handling Errors . . . . . . . . . . . . . . . . . . . 115
8.5 Iteration C4: Finishing the Cart . . . . . . . . . . . . . . . . . . 120
9 Task D: Add a Dash of Ajax 124
9.1 Iteration D1: Moving the Cart . . . . . . . . . . . . . . . . . . . 125
9.2 Iteration D2: Creating an Ajax-Based Cart . . . . . . . . . . . . 130
9.3 Iteration D3: Highlighting Changes . . . . . . . . . . . . . . . . 133
9.4 Iteration D4: Hiding an Empty Cart . . . . . . . . . . . . . . . . 136
9.5 Iteration D5: Degrading If Javascript Is Disabled . . . . . . . . 139
9.6 What We Just Did . . . . . . . . . . . . . . . . . . . . . . . . . . 140
10 Task E: Check Out! 142
10.1 Iteration E1: Capturing an Order . . . . . . . . . . . . . . . . . 142
11 Task F: Administration 159
11.1 Iteration F1: Adding Users . . . . . . . . . . . . . . . . . . . . . 159
11.2 Iteration F2: Logging In . . . . . . . . . . . . . . . . . . . . . . . 168
11.3 Iteration F3: Limiting Access . . . . . . . . . . . . . . . . . . . . 171
11.4 Iteration F4: Adding a Sidebar, More Administration . . . . . . 174
Report erratum
this copy is (P1.0 printing, March 2009)
CONTENTS 7
12 Task G: One Last Wafer-Thin Change 181
12.1 Generating the XML Feed . . . . . . . . . . . . . . . . . . . . . . 181
12.2 Finishing Up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
13 Task I: Internationalization 193
13.1 Iteration I1: Enabling Translation . . . . . . . . . . . . . . . . . 193
13.2 Iteration I2: Exploring Strategies for Content . . . . . . . . . . 207
14 Task T: Testing 210
14.1 Tests Baked Right In . . . . . . . . . . . . . . . . . . . . . . . . 210
14.2 Unit Testing of Models . . . . . . . . . . . . . . . . . . . . . . . . 211
14.3 Functional Testing of Controllers . . . . . . . . . . . . . . . . . 224
14.4 Integration Testing of Applications . . . . . . . . . . . . . . . . 240
14.5 Performance Testing . . . . . . . . . . . . . . . . . . . . . . . . . 249
14.6 Using Mock Objects . . . . . . . . . . . . . . . . . . . . . . . . . 253
Part III—Working with the Rails Framework 256
15 Rails in Depth 257
15.1 So, Where’s Rails? . . . . . . . . . . . . . . . . . . . . . . . . . . 257
15.2 Directory Structure . . . . . . . . . . . . . . . . . . . . . . . . . 257
15.3 Rails Configuration . . . . . . . . . . . . . . . . . . . . . . . . . 264
15.4 Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . 268
15.5 Logging in Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
15.6 Debugging Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
15.7 What’s Next . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
16 Active Support 275
16.1 Generally Available Extensions . . . . . . . . . . . . . . . . . . 275
16.2 Enumerations and Arrays . . . . . . . . . . . . . . . . . . . . . 276
16.3 Hashes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
16.4 String Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . 278
16.5 Extensions to Numbers . . . . . . . . . . . . . . . . . . . . . . . 281
16.6 Time and Date Extensions . . . . . . . . . . . . . . . . . . . . . 282
16.7 An Extension to Ruby Symbols . . . . . . . . . . . . . . . . . . 284
16.8 with_options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
16.9 Unicode Support . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
17 Migrations 291
17.1 Creating and Running Migrations . . . . . . . . . . . . . . . . . 293
17.2 Anatomy of a Migration . . . . . . . . . . . . . . . . . . . . . . . 295
17.3 Managing Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
17.4 Data Migrations . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
Report erratum
this copy is (P1.0 printing, March 2009)
CONTENTS 8
17.5 Advanced Migrations . . . . . . . . . . . . . . . . . . . . . . . . 307
17.6 When Migrations Go Bad . . . . . . . . . . . . . . . . . . . . . . 311
17.7 Schema Manipulation Outside Migrations . . . . . . . . . . . . 312
17.8 Managing Migrations . . . . . . . . . . . . . . . . . . . . . . . . 313
18 Active Record: The Basics 315
18.1 Tables and Classes . . . . . . . . . . . . . . . . . . . . . . . . . 316
18.2 Columns and Attributes . . . . . . . . . . . . . . . . . . . . . . 316
18.3 Primary Keys and ids . . . . . . . . . . . . . . . . . . . . . . . . 320
18.4 Connecting to the Database . . . . . . . . . . . . . . . . . . . . 322
18.5 Create, Read, Update, Delete (CRUD) . . . . . . . . . . . . . . . 327
18.6 Aggregation and Structured Data . . . . . . . . . . . . . . . . . 346
18.7 Miscellany . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
19 Active Record: Relationships Between Tables 357
19.1 Creating Foreign Keys . . . . . . . . . . . . . . . . . . . . . . . . 358
19.2 Specifying Relationships in Models . . . . . . . . . . . . . . . . 360
19.3 belongs_to and has_xxx Declarations . . . . . . . . . . . . . . . 362
19.4 Joining to Multiple Tables . . . . . . . . . . . . . . . . . . . . . 377
19.5 Self-referential Joins . . . . . . . . . . . . . . . . . . . . . . . . . 387
19.6 Acts As . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388
19.7 When Things Get Saved . . . . . . . . . . . . . . . . . . . . . . . 392
19.8 Preloading Child Rows . . . . . . . . . . . . . . . . . . . . . . . 394
19.9 Counters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
20 Active Record: Object Life Cycle 397
20.1 Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
20.2 Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
20.3 Advanced Attributes . . . . . . . . . . . . . . . . . . . . . . . . . 414
20.4 Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
21 Action Controller: Routing and URLs 425
21.1 The Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
21.2 Routing Requests . . . . . . . . . . . . . . . . . . . . . . . . . . 426
21.3 Resource-Based Routing . . . . . . . . . . . . . . . . . . . . . . 441
21.4 Testing Routing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
22 Action Controller and Rails 461
22.1 Action Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461
22.2 Cookies and Sessions . . . . . . . . . . . . . . . . . . . . . . . . 473
22.3 Flash: Communicating Between Actions . . . . . . . . . . . . . 486
22.4 Filters and Verification . . . . . . . . . . . . . . . . . . . . . . . 488
22.5 Caching, Part One . . . . . . . . . . . . . . . . . . . . . . . . . . 496
22.6 The Problem with GET Requests . . . . . . . . . . . . . . . . . . 505
Report erratum
this copy is (P1.0 printing, March 2009)
CONTENTS 9
23 Action View 508
23.1 Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
23.2 Using Helpers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
23.3 Helpers for Formatting, Linking, and Pagination . . . . . . . . 515
23.4 How Forms Work . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
23.5 Forms That Wrap Model Objects . . . . . . . . . . . . . . . . . . 524
23.6 Custom Form Builders . . . . . . . . . . . . . . . . . . . . . . . 537
23.7 Working with Nonmodel Fields . . . . . . . . . . . . . . . . . . . 541
23.8 Uploading Files to Rails Applications . . . . . . . . . . . . . . . 544
23.9 Layouts and Components . . . . . . . . . . . . . . . . . . . . . . 548
23.10 Caching, Part Two . . . . . . . . . . . . . . . . . . . . . . . . . . 555
23.11 Adding New Templating Systems . . . . . . . . . . . . . . . . . 560
24 The Web, v2.0 563
24.1 Prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563
24.2 Script.aculo.us . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
24.3 RJS Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
24.4 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 607
25 Action Mailer 609
25.1 Sending E-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609
25.2 Receiving E-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . 620
25.3 Testing E-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . 622
26 Active Resources 625
26.1 Alternatives to Active Resource . . . . . . . . . . . . . . . . . . 625
26.2 Show Me the Code! . . . . . . . . . . . . . . . . . . . . . . . . . . 628
26.3 Relationships and Collections . . . . . . . . . . . . . . . . . . . 631
26.4 Pulling It All Together . . . . . . . . . . . . . . . . . . . . . . . . 634
Part IV—Securing and Deploying Your Application 636
27 Securing Your Rails Application 637
27.1 SQL Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 637
27.2 Creating Records Directly from Form Parameters . . . . . . . 640
27.3 Don’t Trust id Parameters . . . . . . . . . . . . . . . . . . . . . 641
27.4 Don’t Expose Controller Methods . . . . . . . . . . . . . . . . . 642
27.5 Cross-Site Scripting (CSS/XSS) . . . . . . . . . . . . . . . . . . 643
27.6 Avoid Session Fixation Attacks . . . . . . . . . . . . . . . . . . 646
27.7 File Uploads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646
27.8 Don’t Store Sensitive Information in the Clear . . . . . . . . . 647
27.9 Use SSL to Transmit Sensitive Information . . . . . . . . . . . 648
27.10 Don’t Cache Authenticated Pages . . . . . . . . . . . . . . . . . 650
27.11 Knowing That It Works . . . . . . . . . . . . . . . . . . . . . . . 650
Report erratum
this copy is (P1.0 printing, March 2009)
CONTENTS 10
28 Deployment and Production 651
28.1 Starting Early . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651
28.2 How a Production Server Works . . . . . . . . . . . . . . . . . . 652
28.3 Installing Passenger . . . . . . . . . . . . . . . . . . . . . . . . . 655
28.4 Worry-Free Deployment with Capistrano . . . . . . . . . . . . . 657
28.5 Checking Up on a Deployed Application . . . . . . . . . . . . . 661
28.6 Production Application Chores . . . . . . . . . . . . . . . . . . . 662
28.7 Moving On to Launch and Beyond . . . . . . . . . . . . . . . . 664
Part V—Appendixes 665
A Introduction to Ruby 666
A.1 Ruby Is an Object-Oriented Language . . . . . . . . . . . . . . 666
A.2 Ruby Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667
A.3 Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
A.4 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 670
A.5 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672
A.6 Arrays and Hashes . . . . . . . . . . . . . . . . . . . . . . . . . . 673
A.7 Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . 674
A.8 Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . 675
A.9 Blocks and Iterators . . . . . . . . . . . . . . . . . . . . . . . . . 675
A.10 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676
A.11 Marshaling Objects . . . . . . . . . . . . . . . . . . . . . . . . . 677
A.12 Interactive Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . 677
A.13 Ruby Idioms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677
A.14 RDoc Documentation . . . . . . . . . . . . . . . . . . . . . . . . 679
B Configuration Parameters 680
B.1 Top-Level Configuration . . . . . . . . . . . . . . . . . . . . . . . 680
B.2 Active Record Configuration . . . . . . . . . . . . . . . . . . . . 682
B.3 Action Controller Configuration . . . . . . . . . . . . . . . . . . 684
B.4 Action View Configuration . . . . . . . . . . . . . . . . . . . . . 686
B.5 Action Mailer Configuration . . . . . . . . . . . . . . . . . . . . 686
B.6 Test Case Configuration . . . . . . . . . . . . . . . . . . . . . . . 688
C Source Code 689
C.1 The Full Depot Application . . . . . . . . . . . . . . . . . . . . . 689
D Resources 727
D.1 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . 727
Index 729
Report erratum
this copy is (P1.0 printing, March 2009)
Tous les jours, à tous points de vue, je vais de mieux en mieux.
Émile Coué
Preface to the Second Edition
It has been eighteen months since I announced the first edition of this book. It
was clear before the book came out that Rails would be big, but I don’t think
anyone back then realized just how significant this framework would turn out
to be.
In the year that followed, Rails went from strength to strength. It was used
as the basis for any number of new, exciting websites. Just as significantly,
large corporations (many of them household names) started to use Rails for
both inward- and outward-facing applications. Rails gained critical acclaim,
too. David Heinemeier Hansson, the creator of Rails, was named Hacker of the
Year at OSCON. Rails won a Jolt Award as best web development tool, and the
first edition of this book received a Jolt Award as best technical book.
But the Rails core team didn’t just sit still, soaking up the praise. Instead,
they’ve been heads-down adding new features and facilities. Rails 1.0, which
came out some months after the first edition hit the streets, added features
such as database migration support, as well as updated Ajax integration.
Rails 1.1, released in the spring of 2006, was a blockbuster, with more than
500 changes since the previous release. Many of these changes are deeply
significant. For example, RJS templates change the way that developers write
Ajax-enabled applications, and the integration testing framework changes the
way these applications can be tested. A lot of work has gone into extending
and enhancing Active Record, which now includes polymorphic associations,
join models, better caching, and a whole lot more.
The time had come to update the book to reflect all this goodness. And, as I
started making the changes, I realized that something else had changed. In the
time since the first book was released, we’d all gained a lot more experience
of just how to write a Rails application. Some stuff that seemed like a great
idea didn’t work so well in practice, and other features that initially seemed
peripheral turned out to be significant. And those new practices meant that
the changes to the book went far deeper than I’d expected. I was no longer
doing a cosmetic sweep through the text, adding a couple of new APIs. Instead,
I found myself rewriting the content. Some chapters from the original have
been removed, and new chapters have been added. Many of the rest have been
PREFACE TO THE SECOND EDITION 12
completely rewritten. So, it became clear that we were looking at a second
edition—basically a new book.
It seems strange to be releasing a second edition at a time when the first
edition is still among the best-selling programming books in the world. But
Rails has changed, and we need to change this book with it.
Enjoy!
Dave Thomas
October 2006
Report erratum
this copy is (P1.0 printing, March 2009)
Preface to the Third Edition
When Dave asked me to join as a coauthor of the third edition of this book,
I was thrilled. After all, it was from the first printing of the first edition of
this book that I had learned Rails. Dave and I also have much in common.
Although he prefers Emacs and Mac OS X and my preferences tend toward
VIM and Ubuntu, we both share a love for the command line and getting
our fingers dirty with code—starting with tangible examples before diving into
heavy theory.
Since the time the first edition was published (and, in fact, since the second
edition), much has changed. Rails is now either preinstalled or packaged for
easy installation on all major development platforms. Rails itself has evolved,
and a number of features that were used in previous examples have been
initially deprecated and subsequently removed. New features have been added,
and much experience has been obtained as to what the best practices are for
using Rails.
As such, this book needs to adapt. Once again.
Sam Ruby
January 2009
Chapter 1
Introduction
Ruby on Rails is a framework that makes it easier to develop, deploy, and
maintain web applications. During the months that followed its initial release,
Rails went from being an unknown toy to being a worldwide phenomenon. It
has won awards, and, more important, it has become the framework of choice
for the implementation of a wide range of so-called Web 2.0 applications. It
isn’t just trendy among hard-core hackers; many multinational companies are
using Rails to create their web applications.
Why is that? There seem to be many reasons.
First, a large number of developers were frustrated with the technologies they
were using to create web applications. It didn’t seem to matter whether they
were using Java, PHP, or .NET—there was a growing sense that their job was
just too damn hard. And then, suddenly, along came Rails, and Rails was
easier.
But easy on its own doesn’t cut it. We’re talking about professional developers
writing real-world websites. They wanted to feel that the applications they
were developing would stand the test of time—that they were designed and
implemented using modern, professional techniques. So, these developers dug
into Rails and discovered it wasn’t just a tool for hacking out sites.
For example, all Rails applications are implemented using the Model-View-
Controller (MVC) architecture. Java developers are used to frameworks such
as Tapestry and Struts, which are based on MVC. But Rails takes MVC further:
when you develop in Rails, there’s a place for each piece of code, and all the
pieces of your application interact in a standard way. It’s as if you start with
the skeleton of an application already prepared.
Professional programmers write tests. And again, Rails delivers. All Rails appli-
cations have testing support baked right in. As you add functionality to the
CHAPTER 1. INTRODUCTION 15
code, Rails automatically creates test stubs for that functionality. The frame-
work makes it easy to test applications, and as a result, Rails applications
tend to get tested.
Rails applications are written in Ruby, a modern, object-oriented scripting
language. Ruby is concise without being unintelligibly terse—you can express
ideas naturally and cleanly in Ruby code. This leads to programs that are easy
to write and (just as important) are easy to read months later.
Rails takes Ruby to the limit, extending it in novel ways that make a pro-
grammer’s life easier. This makes our programs shorter and more readable.
It also allows us to perform tasks that would normally be done in external
configuration files inside the codebase instead. This makes it far easier to see
what’s happening. The following code defines the model class for a project.
Don’t worry about the details for now. Instead, just think about how much
information is being expressed in a few lines of code.
class Project < ActiveRecord::Base
belongs_to :portfolio
has_one :project_manager
has_many :milestones
has_many :deliverables, :through => :milestones
validates_presence_of :name, :description
validates_acceptance_of :non_disclosure_agreement
validates_uniqueness_of :short_name
end
Developers who came to Rails also found a strong philosophical underpinning.
The design of Rails was driven by a couple of key concepts: DRY and conven-
tion over configuration. DRY stands for don’t repeat yourself —every piece of
knowledge in a system should be expressed in just one place. Rails uses the
power of Ruby to bring that to life. You’ll find very little duplication in a Rails
application; you say what you need to say in one place—a place often sug-
gested by the conventions of the MVC architecture—and then move on. For
programmers used to other web frameworks, where a simple change to the
schema could involve them in half a dozen or more code changes, this was a
revelation.
Convention over configuration is crucial, too. It means that Rails has sensi-
ble defaults for just about every aspect of knitting together your application.
Follow the conventions, and you can write a Rails application using less code
than a typical Java web application uses in XML configuration. If you need to
override the conventions, Rails makes that easy, too.
Developers coming to Rails found something else, too. Rails is new, and the
core team of developers understands the new Web. Rails isn’t playing catch-up
with the new de facto web standards; it’s helping define them. And Rails makes
Report erratum
this copy is (P1.0 printing, March 2009)
RAILS IS AGILE 16
it easy for developers to integrate features such as Ajax and RESTful interfaces
into their code, because support is built in. (And if you’re not familiar with Ajax
and REST interfaces, never fear—we’ll explain them later in the book.)
Developers are worried about deployment, too. They found that with Rails you
can deploy successive releases of your application to any number of servers
with a single command (and roll them back equally easily should the release
prove to be somewhat less than perfect).
Rails was extracted from a real-world, commercial application. It turns out
that the best way to create a framework is to find the central themes in a
specific application and then bottle them up in a generic foundation of code.
When you’re developing your Rails application, you’re starting with half of a
really good application already in place.
But there’s something else to Rails—something that’s hard to describe. Some-
how, it just feels right. Of course, you’ll have to take our word for that until
you write some Rails applications for yourself (which should be in the next 45
minutes or so...). That’s what this book is all about.
1.1 Rails Is Agile
The title of this book is Agile Web Development with Rails. You may be sur-
prised to discover that we don’t have explicit sections on applying agile prac-
tices X, Y, and Z to Rails coding.
The reason is both simple and subtle. Agility is part of the fabric of Rails.
Let’s look at the values expressed in the Agile Manifesto as a set of four pref-
erences:1
Agile development favors the following:
• Individuals and interactions over processes and tools
• Working software over comprehensive documentation
• Customer collaboration over contract negotiation
• Responding to change over following a plan
Rails is all about individuals and interactions. There are no heavy toolsets,
no complex configurations, and no elaborate processes. There are just small
groups of developers, their favorite editors, and chunks of Ruby code. This
leads to transparency; what the developers do is reflected immediately in what
the customer sees. It’s an intrinsically interactive process.
Rails doesn’t denounce documentation. Rails makes it trivially easy to cre-
ate HTML documentation for your entire codebase. But the Rails development
process isn’t driven by documents. You won’t find 500-page specifications at
1. http://agilemanifesto.org/. Dave Thomas was one of the seventeen authors of this document.
Report erratum
this copy is (P1.0 printing, March 2009)
FINDING YOUR WAY AROUND 17
the heart of a Rails project. Instead, you’ll find a group of users and devel-
opers jointly exploring their need and the possible ways of answering that
need. You’ll find solutions that change as both the developers and the users
become more experienced with the problems they’re trying to solve. You’ll find
a framework that delivers working software early in the development cycle.
This software may be rough around the edges, but it lets the users start to get
a glimpse of what you’ll be delivering.
In this way, Rails encourages customer collaboration. When customers see
just how quickly a Rails project can respond to change, they start to trust
that the team can deliver what’s required, not just what has been requested.
Confrontations are replaced by “What if?” sessions.
That’s all tied to the idea of being able to respond to change. The strong, almost
obsessive, way that Rails honors the DRY principle means that changes to
Rails applications impact a lot less code than the same changes would in other
frameworks. And since Rails applications are written in Ruby, where concepts
can be expressed accurately and concisely, changes tend to be localized and
easy to write. The deep emphasis on both unit and functional testing, along
with support for test fixtures and stubs during testing, gives developers the
safety net they need when making those changes. With a good set of tests in
place, changes are less nerve-racking.
Rather than constantly trying to tie Rails processes to the agile principles,
we’ve decided to let the framework speak for itself. As you read through the
tutorial chapters, try to imagine yourself developing web applications this way:
working alongside your customers and jointly determining priorities and solu-
tions to problems. Then, as you read the deeper reference material in the back,
see how the underlying structure of Rails can enable you to meet your cus-
tomers’ needs faster and with less ceremony.
One last point about agility and Rails: although it’s probably unprofessional
to mention this, think how much fun the coding will be.
1.2 Finding Your Way Around
The first two parts of this book are an introduction to the concepts behind
Rails and an extended example—we build a simple online store. This is the
place to start if you’re looking to get a feel for Rails programming. In fact, most
folks seem to enjoy building the application along with the book. If you don’t
want to do all that typing, you can cheat and download the source code (a
compressed tar archive or a zip file).2
2. http://www.pragprog.com/titles/rails3/code.html has the links for the downloads.
Report erratum
this copy is (P1.0 printing, March 2009)
FINDING YOUR WAY AROUND 18
The third part of the book, starting on page 257, is a detailed look at all the
functions and facilities of Rails. This is where you’ll go to find out how to
use the various Rails components and how to deploy your Rails applications
efficiently and safely.
Along the way, you’ll see various conventions we’ve adopted.
Live Code
Most of the code snippets we show come from full-length, running exam-
ples that you can download. To help you find your way, if a code listing
can be found in the download, there’ll be a bar above the snippet (just
like the one here).
Download work/demo1/app/controllers/say_controller.rb
class SayController < ApplicationController
def hello
end
end
This contains the path to the code within the download. If you’re reading
the PDF version of this book and your PDF viewer supports hyperlinks,
you can click the bar, and the code should appear in a browser window.
Some browsers (such as Safari) will mistakenly try to interpret some of
the templates as HTML. If this happens, view the source of the page to
see the real source code.
And in some cases involving the modification of an existing file where the
lines to be changed may not be immediately obvious, you will also see
some helpful little triangles on the left of the lines that you will need to
change. Two such lines are indicated in the previous code.
Ruby Tips
Although you need to know Ruby to write Rails applications, we realize
that many folks reading this book will be learning both Ruby and Rails
at the same time. Appendix A, on page 666, is a (very) brief introduction
to the Ruby language. When we use a Ruby-specific construct for the
first time, we’ll cross-reference it to that appendix. For example, this
paragraph contains a gratuitous use of :name, a Ruby symbol. In the :name
֒
→ page 668
margin, you’ll see an indication that symbols are explained on page 668.
So, if you don’t know Ruby or if you need a quick refresher, you might
want to read Appendix A, on page 666, before you go too much further.
There’s a lot of code in this book....
David Says...
Every now and then you’ll come across a David Says... sidebar. Here’s
where David Heinemeier Hansson gives you the real scoop on some par-
ticular aspect of Rails—rationales, tricks, recommendations, and more.
Report erratum
this copy is (P1.0 printing, March 2009)
ACKNOWLEDGMENTS 19
Because he’s the fellow who invented Rails, these are the sections to read
if you want to become a Rails pro.
Joe Asks...
Joe, the mythical developer, sometimes pops up to ask questions about
stuff we talk about in the text. We answer these questions as we go along.
This book isn’t a reference manual for Rails. We show most of the modules and
most of their methods, either by example or narratively in the text, but we don’t
have hundreds of pages of API listings. There’s a good reason for this—you get
that documentation whenever you install Rails, and it’s guaranteed to be more
up-to-date than the material in this book. If you install Rails using RubyGems
(which we recommend), simply start the gem documentation server (using the
command gem server), and you can access all the Rails APIs by pointing your
browser at http://localhost:8808.
Rails Versions
This book is based on Rails 2.0. In particular, its code has been run against
the Rails 2.2.2 RubyGem.
Previous versions of Rails contain incompatibilities with 2.2.2, and it is more
than likely that future versions will, too.
1.3 Acknowledgments
You’d think that producing a third edition of a book would be easy. After all,
you already have all the text. It’s just a tweak to some code here and a minor
wording change there, and you’re done. You’d think....
It’s difficult to tell exactly, but our impression is that creating each edition of
Agile Web Development with Rails took about as much effort as the first edi-
tion. Rails is constantly evolving and, as it does, so has this book. Parts of the
Depot application were rewritten several times, and all of the narrative was
updated. The emphasis on REST and the addition of the deprecation mecha-
nism all changed the structure of the book as what was once hot became just
lukewarm.
So, this book would not exist without a massive amount of help from the
Ruby and Rails communities. As with the original, this book was released as
a beta book: early versions were posted as PDFs, and people made comments
online. And comment they did: more than 1,200 suggestions and bug reports
were posted. The vast majority ended up being incorporated, making this book
immeasurably more useful than it would have been. Thank you all, both for
supporting the beta book program and for contributing so much valuable
feedback.
Report erratum
this copy is (P1.0 printing, March 2009)
ACKNOWLEDGMENTS 20
As with the first edition, the Rails core team was incredibly helpful, answering
questions, checking out code fragments, and fixing bugs. A big thank you to
the following:
Scott Barron (htonl), Jamis Buck (minam), Thomas Fuchs (madrobby),
Jeremy Kemper (bitsweat), Michael Koziarski (nzkoz),
Marcel Molina Jr, (noradio), Rick Olson (technoweenie),
Nicholas Seckar (Ulysses), Sam Stephenson (sam), Tobias Lütke (xal),
and Florian Weber (csshsh)
We’d like to thank the folks who contributed the specialized chapters to the
book: Leon Breedt, Mike Clark, James Duncan Davidson, Justin Gehtland,
and Andreas Schwarz.
From Sam Ruby
This effort has turned out to be both harder and more rewarding than I would
have ever anticipated. It’s been harder in that Rails has changed so much and
there has been so much to learn (in terms of Rails 2.0, in terms of SQLite 3,
and also in terms of working with a different publisher, operating system, and
toolset). But I can’t begin to express how much I like the beta book program—
the readers who this book has attracted so far have been great, and their
comments, questions, and feedback have been most appreciated.
Sam Ruby
January 2009
rubys@intertwingly.net
From Dave Thomas
I keep promising myself that each book will be the last, if for no other reason
than each takes me away from my family for months at a time. Once again:
Juliet, Zachary, and Henry—thank you for everything.
Dave Thomas
November 2006
dave@pragprog.com
“Agile Web Development with Rails...I found it
in our local bookstore, and it seemed great!”
—Dave’s mum
Report erratum
this copy is (P1.0 printing, March 2009)
Part I
Getting Started
Chapter 2
The Architecture of Rails Applications
One of the interesting features of Rails is that it imposes some fairly serious
constraints on how you structure your web applications. Surprisingly, these
constraints make it easier to create applications—a lot easier. Let’s see why.
2.1 Models, Views, and Controllers
Back in 1979, Trygve Reenskaug came up with a new architecture for develop-
ing interactive applications. In his design, applications were broken into three
types of components: models, views, and controllers.
The model is responsible for maintaining the state of the application. Some-
times this state is transient, lasting for just a couple of interactions with the
user. Sometimes the state is permanent and will be stored outside the appli-
cation, often in a database.
A model is more than just data; it enforces all the business rules that apply
to that data. For example, if a discount shouldn’t be applied to orders of less
than $20, the model will enforce the constraint. This makes sense; by putting
the implementation of these business rules in the model, we make sure that
nothing else in the application can make our data invalid. The model acts as
both a gatekeeper and a data store.
The view is responsible for generating a user interface, normally based on
data in the model. For example, an online store will have a list of products
to be displayed on a catalog screen. This list will be accessible via the model,
but it will be a view that accesses the list from the model and formats it for
the end user. Although the view may present the user with various ways of
inputting data, the view itself never handles incoming data. The view’s work
is done once the data is displayed. There may well be many views that access
the same model data, often for different purposes. In the online store, there’ll
MODELS, VIEWS, AND CONTROLLERS 23
Database
Controller
View Model
! Browser sends request
!
"
" Controller interacts with model
#
# Controller invokes view
$ View renders next browser screen
$
Figure 2.1: The Model-View-Controller architecture
be a view that displays product information on a catalog page and another set
of views used by administrators to add and edit products.
Controllers orchestrate the application. Controllers receive events from the
outside world (normally user input), interact with the model, and display an
appropriate view to the user.
This triumvirate—the model, view, and controller—together form an architec-
ture known as MVC. MVC is shown in abstract terms in Figure 2.1.
MVC was originally intended for conventional GUI applications, where devel-
opers found the separation of concerns led to far less coupling, which in turn
made the code easier to write and maintain. Each concept or action was
expressed in just one well-known place. Using MVC was like constructing a
skyscraper with the girders already in place—it was a lot easier to hang the
rest of the pieces with a structure already there.
In the software world, we often ignore good ideas from the past as we rush
headlong to meet the future. When developers first started producing web
applications, they went back to writing monolithic programs that intermixed
presentation, database access, business logic, and event handling in one big
ball of code. But ideas from the past slowly crept back in, and folks started
experimenting with architectures for web applications that mirrored the 20-
year-old ideas in MVC. The results were frameworks such as WebObjects,
Struts, and JavaServer Faces. All are based (with varying degrees of fidelity)
on the ideas of MVC.
Report erratum
this copy is (P1.0 printing, March 2009)
MODELS, VIEWS, AND CONTROLLERS 24
Database
! http://my.url/store/add_to_cart/123
!
"
# Controller interacts with model
#
$ Controller invokes view
%&View renders next browser screen
$
Store
Controller
Routing
Active
Record
Model
Display
Cart
View
%
" Routing finds store controller
Figure 2.2: Rails and MVC
Ruby on Rails is an MVC framework, too. Rails enforces a structure for your
application—you develop models, views, and controllers as separate chunks of
functionality, and it knits them all together as your program executes. One of
the joys of Rails is that this knitting process is based on the use of intelligent
defaults so that you typically don’t need to write any external configuration
metadata to make it all work. This is an example of the Rails philosophy of
favoring convention over configuration.
In a Rails application, an incoming request is first sent to a router, which
works out where in the application the request should be sent and how the
request itself should be parsed. Ultimately, this phase identifies a particular
method (called an action in Rails parlance) somewhere in the controller code.
The action might look at data in the request, it might interact with the model,
and it might cause other actions to be invoked. Eventually the action prepares
information for the view, which renders something to the user.
Rails handles an incoming request as shown in Figure 2.2. In this example, the
application has previously displayed a product catalog page, and the user has
just clicked the Add to Cart button next to one of the products. This button
links to http://my.url/store/add_to_cart/123, where add_to_cart is an action in our
application and 123 is our internal id for the selected product.1
1. We cover the format of Rails URLs later in the book. However, it’s worth pointing out here
that having URLs perform actions such as “add to cart” can be dangerous. For more details, see
Section 22.6, The Problem with GET Requests, on page 505.
Report erratum
this copy is (P1.0 printing, March 2009)
ACTIVE RECORD: RAILS MODEL SUPPORT 25
The routing component receives the incoming request and immediately picks
it apart. In this simple case, it takes the first part of the path, store, as the
name of the controller and the second part, add_to_cart, as the name of an
action. The last part of the path, 123, is by convention extracted into an internal
parameter called id. As a result of all this analysis, the router knows it has to
invoke the add_to_cart method in the controller class StoreController (we’ll talk
about naming conventions on page 268).
The add_to_cart method handles user requests. In this case, it finds the current
user’s shopping cart (which is an object managed by the model). It also asks
the model to find the information for product 123. It then tells the shopping
cart to add that product to itself. (See how the model is being used to keep
track of all the business data? The controller tells it what to do, and the model
knows how to do it.)
Now that the cart includes the new product, we can show it to the user. The
controller invokes the view code, but before it does, it arranges things so that
the view has access to the cart object from the model. In Rails, this invocation
is often implicit; again, conventions help link a particular view with a given
action.
That’s all there is to an MVC web application. By following a set of conven-
tions and partitioning your functionality appropriately, you’ll discover that
your code becomes easier to work with and your application becomes easier to
extend and maintain. Seems like a good trade.
If MVC is simply a question of partitioning your code a particular way, you
might be wondering why you need a framework such as Ruby on Rails. The
answer is straightforward: Rails handles all of the low-level housekeeping for
you—all those messy details that take so long to handle by yourself—and lets
you concentrate on your application’s core functionality. Let’s see how....
2.2 Active Record: Rails Model Support
In general, we’ll want our web applications to keep their information in a rela-
tional database. Order-entry systems will store orders, line items, and cus-
tomer details in database tables. Even applications that normally use unstruc-
tured text, such as weblogs and news sites, often use databases as their back-
end data store.
Although it might not be immediately apparent from the SQL2
you use to
access them, relational databases are actually designed around mathematical
set theory. Although this is good from a conceptual point of view, it makes it
difficult to combine relational databases with object-oriented (OO) program-
ming languages. Objects are all about data and operations, and databases are
2. SQL, referred to by some as Structured Query Language, is the language used to query and
update relational databases.
Report erratum
this copy is (P1.0 printing, March 2009)
ACTIVE RECORD: RAILS MODEL SUPPORT 26
all about sets of values. Operations that are easy to express in relational terms
are sometimes difficult to code in an OO system. The reverse is also true.
Over time, folks have worked out ways of reconciling the relational and OO
views of their corporate data. Let’s look at two different approaches. One orga-
nizes your program around the database; the other organizes the database
around your program.
Database-centric Programming
The first folks who coded against relational databases programmed in proce-
dural languages such as C and COBOL. These folks typically embedded SQL
directly into their code, either as strings or by using a preprocessor that con-
verted SQL in their source into lower-level calls to the database engine.
The integration meant that it became natural to intertwine the database logic
with the overall application logic. A developer who wanted to scan through
orders and update the sales tax in each order might write something exceed-
ingly ugly, such as this:
EXEC SQL BEGIN DECLARE SECTION;
int id;
float amount;
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE c1 AS CURSOR FOR select id, amount from orders;
while (1) {
float tax;
EXEC SQL WHENEVER NOT FOUND DO break;
EXEC SQL FETCH c1 INTO :id, :amount;
tax = calc_sales_tax(amount)
EXEC SQL UPDATE orders set tax = :tax where id = :id;
}
EXEC SQL CLOSE c1;
EXEC SQL COMMIT WORK;
Scary stuff, eh? Don’t worry. We won’t be doing any of this, even though this
style of programming is common in scripting languages such as Perl and PHP.
It’s also available in Ruby. For example, we could use Ruby’s DBI library to
produce similar-looking code (like the previous example, this one has no error
checking): Method definition
֒
→ page 668
def update_sales_tax
update = @db.prepare("update orders set tax=? where id=?")
@db.select_all("select id, amount from orders") do |id, amount|
tax = calc_sales_tax(amount)
update.execute(tax, id)
end
end
Report erratum
this copy is (P1.0 printing, March 2009)
ACTIVE RECORD: RAILS MODEL SUPPORT 27
This approach is concise and straightforward and indeed is widely used. It
seems like an ideal solution for small applications. However, there is a prob-
lem. Intermixing business logic and database access like this can make it hard
to maintain and extend the applications in the future. And you still need to
know SQL just to get started on your application.
Say, for example, our enlightened state government passes a new law that
says we have to record the date and time that sales tax was calculated. That’s
not a problem, we think. We just have to get the current time in our loop, add
a column to the SQL update statement, and pass the time to the execute call.
But what happens if we set the sales tax column in many different places
in the application? Now we’ll need to go through and find all these places,
updating each. We have duplicated code, and (if we miss a place where the
column is set) we have a source of errors.
In regular programming, object orientation has taught us that encapsulation
solves these types of problems. We’d wrap everything to do with orders in a
class; we’d have a single place to update when the regulations change.
Folks have extended these ideas to database programming. The basic premise
is trivially simple. We wrap access to the database behind a layer of classes.
The rest of our application uses these classes and their objects—it never inter-
acts with the database directly. This way we’ve encapsulated all the schema-
specific stuff into a single layer and decoupled our application code from the
low-level details of database access. In the case of our sales tax change, we’d
simply change the class that wrapped the orders table to update the times-
tamp whenever the sales tax was changed.
In practice, this concept is harder to implement than it might appear. Real-life
database tables are interconnected (an order might have multiple line items,
for example), and we’d like to mirror this in our objects: the order object should
contain a collection of line item objects. But we then start getting into issues of
object navigation, performance, and data consistency. When faced with these
complexities, the industry did what it always does; it invented a three-letter
acronym: ORM, which stands for object-relational mapping. Rails uses ORM.
Object-Relational Mapping
ORM libraries map database tables to classes. If a database has a table called
orders, our program will have a class named Order. Rows in this table corre-
spond to objects of the class—a particular order is represented as an object of
class Order. Within that object, attributes are used to get and set the individual
columns. Our Order object has methods to get and set the amount, the sales
tax, and so on.
Report erratum
this copy is (P1.0 printing, March 2009)
ACTIVE RECORD: RAILS MODEL SUPPORT 28
In addition, the Rails classes that wrap our database tables provide a set of
class-level methods that perform table-level operations. For example, we might
need to find the order with a particular id. This is implemented as a class
method that returns the corresponding Order object. In Ruby code, this might class method
֒
→ page 670
look like this:
order = Order.find(1) puts
֒
→ page 668
puts "Customer #{order.customer_id}, amount=#{order.amount}"
Sometimes these class-level methods return collections of objects:
iterating
֒
→ page 675
Order.find(:all, :conditions => "name='dave'").each do |order|
puts order.amount
end
Finally, the objects corresponding to individual rows in a table have methods
that operate on that row. Probably the most widely used is save, the operation
that saves the row to the database:
Order.find(:all, :conditions => "name='dave'").each do |order|
order.discount = 0.5
order.save
end
So, an ORM layer maps tables to classes, rows to objects, and columns to
attributes of those objects. Class methods are used to perform table-level oper-
ations, and instance methods perform operations on the individual rows.
In a typical ORM library, you supply configuration data to specify the map-
pings between entities in the database and entities in the program. Program-
mers using these ORM tools often find themselves creating and maintaining a
boatload of XML configuration files.
Active Record
Active Record is the ORM layer supplied with Rails. It closely follows the stan-
dard ORM model: tables map to classes, rows to objects, and columns to object
attributes. It differs from most other ORM libraries in the way it is configured.
By relying on convention and starting with sensible defaults, Active Record
minimizes the amount of configuration that developers perform. To illustrate
this, here’s a program that uses Active Record to wrap our orders table:
require 'active_record'
class Order < ActiveRecord::Base
end
order = Order.find(1)
order.discount = 0.5
order.save
Report erratum
this copy is (P1.0 printing, March 2009)
ACTION PACK: THE VIEW AND CONTROLLER 29
This code uses the new Order class to fetch the order with an id of 1 and modify
the discount. (We’ve omitted the code that creates a database connection for
now.) Active Record relieves us of the hassles of dealing with the underlying
database, leaving us free to work on business logic.
But Active Record does more than that. As you’ll see when we develop our
shopping cart application, starting on page 63, Active Record integrates seam-
lessly with the rest of the Rails framework. If a web form sends the application
data related to a business object, Active Record can extract it into our model.
Active Record supports sophisticated validation of model data, and if the form
data fails validations, the Rails views can extract and format errors with just
a single line of code.
Active Record is the solid model foundation of the Rails MVC architecture.
That’s why we devote three chapters to it, starting on page 315.
2.3 Action Pack: The View and Controller
When you think about it, the view and controller parts of MVC are pretty
intimate. The controller supplies data to the view, and the controller receives
events from the pages generated by the views. Because of these interactions,
support for views and controllers in Rails is bundled into a single component,
Action Pack.
Don’t be fooled into thinking that your application’s view code and controller
code will be jumbled up just because Action Pack is a single component. Quite
the contrary; Rails gives you the separation you need to write web applications
with clearly demarcated code for control and presentation logic.
View Support
In Rails, the view is responsible for creating either all or part of a page to be
displayed in a browser.3
At its simplest, a view is a chunk of HTML code that
displays some fixed text. More typically you’ll want to include dynamic content
created by the action method in the controller.
In Rails, dynamic content is generated by templates, which come in three
flavors. The most common templating scheme, called Embedded Ruby (ERb),
embeds snippets of Ruby code within a view document.4
This approach is very
flexible, but purists sometimes complain that it violates the spirit of MVC.
By embedding code in the view, we risk adding logic that should be in the
model or the controller. This complaint is largely groundless, because views
contained active code even in the original MVC architectures. Maintaining a
3. Or an XML response, or an e-mail, or.... The key point is that views generate the response back
to the user.
4. This approach might be familiar to web developers working with PHP or Java’s JSP technology.
Report erratum
this copy is (P1.0 printing, March 2009)
ACTION PACK: THE VIEW AND CONTROLLER 30
clean separation of concerns is part of the job of the developer. (We look at
HTML templates in Section 23.1, ERb Templates, on page 511.)
XML Builder can also be used to construct XML documents using Ruby code—
the structure of the generated XML will automatically follow the structure of
the code. We discuss xml.builder templates starting on page 510.
Rails also provides RJS views. These allow you to create JavaScript fragments
on the server that are then executed on the browser. This is great for creating
dynamic Ajax interfaces. We talk about these starting on page 600.
And the Controller!
The Rails controller is the logical center of your application. It coordinates the
interaction between the user, the views, and the model. However, Rails handles
most of this interaction behind the scenes; the code you write concentrates on
application-level functionality. This makes Rails controller code remarkably
easy to develop and maintain.
The controller is also home to a number of important ancillary services:
• It is responsible for routing external requests to internal actions. It han-
dles people-friendly URLs extremely well.
• It manages caching, which can give applications orders-of-magnitude
performance boosts.
• It manages helper modules, which extend the capabilities of the view
templates without bulking up their code.
• It manages sessions, giving users the impression of ongoing interaction
with our applications.
There’s a lot to Rails. Rather than attack it component by component, let’s roll
up our sleeves and write a couple of working applications. In the next chapter,
we’ll install Rails. After that, we’ll write something simple, just to make sure
we have everything installed correctly. In Chapter 5, The Depot Application, on
page 63, we’ll start writing something more substantial—a simple online store
application.
Report erratum
this copy is (P1.0 printing, March 2009)
Chapter 3
Installing Rails
3.1 Your Shopping List
To get Rails running on your system, you’ll need the following:
• A Ruby interpreter. Rails is written in Ruby, and you’ll be writing your
applications in Ruby too. The Rails team now recommends Ruby version
1.8.7.
• Ruby on Rails. This book was written using Rails version 2 (specifically
the 2.2.2 Rails RubyGem).1
• Some libraries.
• A database. We’re using SQLite 3 in this book.
For a development machine, that’s about all you’ll need (apart from an editor,
and we’ll talk about editors separately). However, if you are going to deploy
your application, you will also need to install a production web server (as a
minimum) along with some support code to let Rails run efficiently. We have a
whole chapter devoted to this, starting on page 651, so we won’t talk about it
more here.
So, how do you get all this installed? It depends on your operating system....
3.2 Installing on Windows
If you’re using Windows for development, you’re in luck, because InstantRails
2.0 is a single download that contains Ruby, Rails, SQLite 3 (version 3.5.4 at
the time of writing), and all the gubbins needed to make them work together. It
even contains an Apache web server and the support code that lets you deploy
high-performance web applications.
1. It also has been tested periodically with Edge Rails and should work there too, but given the
uncertain nature of the Edge at any point in time, there are no guarantees that this will work.
INSTALLING ON WINDOWS 32
1. Create a folder to contain the InstantRails installation. The path to the
folder cannot contain any spaces (so C:Program Files would be a poor
choice).
2. Visit the InstantRails website,2
and follow the link to download the latest
.zip file. (It’s about 70MB, so make a pot of tea before starting if you’re on
a slow connection.) Put it into the directory you created in step 1.
3. You’ll need to unzip the archive if your system doesn’t do it automatically.
4. Navigate to the InstantRails-2.0 directory, and start InstantRails by double-
clicking the InstantRails icon (it’s the big red I).
• If you see a pop-up asking whether it’s OK to regenerate configura-
tion files, say OK .
• If you see a security alert saying that Apache has been blocked
by the firewall, well...we’re not going to tell you whether to block
it or unblock it. For the purposes of this book, we aren’t going to be
using Apache, so it doesn’t matter. The safest course of action is to
say Keep Blocking . If you know what you are doing and you aren’t
running IIS on your machine, you can unblock the port and use
Apache later.
You should see a small InstantRails window appear. You can use this to
monitor and control Rails applications. However, we’ll be digging a lit-
tle deeper than this, so we’ll be using a console window. To start this,
click the I button in the top-left corner of the InstantRails window (the
button has a black I with a red dot in the lower right). From the menu,
select Rails Applications..., followed by Open Ruby Console Window. You
should see a command window pop up, and you’ll be sitting in the
rails_apps directory, as shown in Figure 3.1, on the next page. You can
verify your versions of Ruby and Rails by typing the commands ruby -v
and rails -v, respectively.
At this point, you’re up and running. But, before you skip to the start of the
next chapter, you should know three important facts.
First, and most important, whenever you want to enter commands in a console
window, you must use a console started from the InstantRails menu. Follow the
same procedure we used previously (clicking the I, and so on). If you bring up
a regular Windows command prompt, stuff just won’t work. (Why? Because
InstantRails is self-contained—it doesn’t install itself into your global Windows
environment. That means all the programs you need are not by default in the
Windows path. You can, with a little fiddling, add them and then use the
regular command window, but the InstantRails way seems just as easy.)
2. http://instantrails.rubyforge.org/wiki/wiki.pl
Report erratum
this copy is (P1.0 printing, March 2009)
INSTALLING ON MAC OS X 33
Figure 3.1: Instant Rails—starting a console
Second, at the time of this writing, InstantRails 2.0 bundles and ships Rails
version 2.0.2. The examples in this book are based on Rails 2.2.2. At any
time you can upgrade your version of Rails to the very latest by opening an
InstantRails console and typing this:
C:rails_apps> gem update --system
C:rails_apps> gem update rails
There is no need to upgrade your version of Ruby, because Ruby 1.8.6 will
work just fine.
Finally, the example sessions in this book are based on execution on a Mac.
Although the ruby and rails commands are exactly the same, the Unix com-
mands are different. This book uses only one Unix command: ls. The Windows
equivalent is dir.
OK, you Windows users are done. You can skip forward to Section 3.5, Choos-
ing a Rails Version, on page 36. See you there.
3.3 Installing on Mac OS X
As of OS X 10.4.6 (Tiger), Mac users have a decent Ruby installation included
as standard. And OS X 10.5 (Leopard) includes Rails itself. However, this is
Rails 1.2.6. So either way, you have some upgrading to do, a bit more for Tiger
than for Leopard, but it’s not too difficult either way.
Report erratum
this copy is (P1.0 printing, March 2009)
INSTALLING ON LINUX 34
Tiger users will also need to upgrade SQLite 3. This can be done via compiling
from source (which sounds scarier than it is). You can find the instructions to
do so at http://www.sqlite.org/download.html.
An alternate way to install SQLite 3 is via the popular MacPorts package,
which you can find at http://www.macports.org/install.php. Although the instruc-
tions look a bit scary, the individual steps are pretty straightforward: run an
installer, run another installer, add two lines to a file, run yet another installer,
and then issue a single command. This may not turn out to be easier than
compiling from source for yourself, but many find the investment to be worth
it because it makes installing further packages as easy as a single command.
So if you have ports installed, let’s upgrade the version of SQLite 3 on your
machine:
sudo port upgrade sqlite3
Both Tiger and Leopard users can use the following commands to update their
system the rest of the way. If you just installed MacPorts, be sure to take heed
of the important note to open a new shell and verify via the env command that
your path and variable changes are in effect. If you haven’t already done so,
install Apple’s XCode Developer Tools (version 3.1 or later for Leopard, 2.4.1 or
later for Tiger), found at the Apple Developer Connection site or on your Mac
OS X installation CDs/DVD.
sudo gem update --system
sudo gem install rails
sudo gem update rake
sudo gem install sqlite3-ruby
The following step is rarely necessary, but it can be helpful if things continue to
go wrong. You can verify which version of SQLite 3 your sqlite3-ruby interface
is bound to by running the following as a stand-alone program, from within
irb, or from within ruby script/console.
require 'rubygems'
require 'sqlite3'
tempname = "test.sqlite#{3+rand}"
db = SQLite3::Database.new(tempname)
puts db.execute('select sqlite_version()')
db.close
File.unlink(tempname)
3.4 Installing on Linux
Start with your platform’s native package management system, be it aptitude,
dpkg, portage, rpm, rug, synaptic, up2date, or yum.
Report erratum
this copy is (P1.0 printing, March 2009)
INSTALLING ON LINUX 35
Upgrading RubyGems
There are many different ways to upgrade RubyGems. Unfortunately, depend-
ing on which version of RubyGems you have installed and what distribution
you are running, not all of the ways work. Be persistent. Try each of the follow-
ing until you find one that works for you.
• Using the gem update system:
sudo gem update --system
• Using the gem designed to update troublesome systems:
sudo gem install rubygems-update
sudo update_rubygems
• Using setup.rb, which is provided with rubygems-update:
sudo gem install rubygems-update
cd /var/lib/gems/1.8/gems/rubygems-update-*
sudo ruby setup.rb
• Finally, installing from source:
wget http://rubyforge.org/frs/download.php/45905/rubygems-1.3.1.tgz
tar xzf rubygems-1.3.1.tgz
cd rubygems-1.3.1
sudo ruby setup.rb
The first step is to install the necessary dependencies. The following instruc-
tions are for Ubuntu 8.10, Intrepid Ibex; you can adapt them as necessary for
your installation:
sudo aptitude update
sudo aptitude install build-essential libopenssl-ruby
sudo aptitude install ruby rubygems ruby1.8-dev libsqlite3-dev
Before proceeding, it is important to verify that the version of RubyGems is at
least 1.3.1. You can find out the version by issuing gem -v. How to upgrade
your version of RubyGems is described in the sidebar on the current page.
sudo gem install rails
sudo gem install sqlite3-ruby
On the last command, you will be prompted to select which gem to install for
your platform. Simply select the latest (topmost) gem that contains the word
ruby in parentheses, and a native extension will be built for you.
You may also need to add /var/lib/gems/1.8/bin to your PATH environment vari-
able. You can do this by adding a line to your .bashrc file:
export PATH=/var/lib/gems/1.8/bin:$PATH
Report erratum
this copy is (P1.0 printing, March 2009)
CHOOSING A RAILS VERSION 36
3.5 Choosing a Rails Version
The previous instructions helped you install the latest version of Rails. But
occasionally you might not want to run with that version. Perhaps a new ver-
sion of Rails has come out since this book has been published, so you want
to be absolutely confident that the examples that you see here exactly match
the version of Rails you are running. Or perhaps you are developing on one
machine but intending to deploy on another machine that contains a version
of Rails that you don’t have any control over.
If either of these situations applies to you, you need to be aware of a few things.
For starters, you can find out all the versions of Rails you have installed using
the gem command:
gem list --local rails
You can also verify what version of Rails you are running as the default by
using the rails --version command. It should return 2.2.2 or later.
Installing another version of Rails is also done via the gem command. Depend-
ing on your operating system, you might need to preface the command with
sudo.
gem install rails --version 2.2.2
Now, having multiple versions of Rails wouldn’t do anybody any good unless
there were a way to pick one. As luck would have it, there is. On any rails
command, you can control which version of Rails is used by inserting the full
version number surrounded by underscores before the first parameter of the
command:
rails _2.2.2_ --version
This is particularly handy when you create a new application, because once
you create an application with a specific version of Rails, it will continue to use
that version of Rails—even if newer versions are installed on the system—until
you decide it is time to upgrade. How to change the version of Rails that your
application is using is described in the sidebar on page 264.
And finally, should you decide to proceed using a version other than 2.2.2,
you are not completely on your own. You can find a list of changes that will
affect you at http://wiki.pragprog.com/changes-to-rails.
3.6 Development Environments
The day-to-day business of writing Rails programs is pretty straightforward.
Everyone works differently; here’s how we work.
Report erratum
this copy is (P1.0 printing, March 2009)
DEVELOPMENT ENVIRONMENTS 37
The Command Line
We do a lot of work at the command line. Although there are an increasing
number of GUI tools that help generate and manage a Rails application, we
find the command line is still the most powerful place to be. It’s worth spending
a little while getting familiar with the command line on your operating system.
Find out how to use it to edit commands that you’re typing, how to search
for and edit previous commands, and how to complete the names of files and
commands as you type.3
Version Control
We keep all our work in a version control system (currently Git). We make a
point of checking a new Rails project into Git when we create it and committing
changes once we have passing tests. We normally commit to the repository
many times an hour.
If you’re working on a Rails project with other people, consider setting up a
continuous integration (CI) system. When anyone checks in changes, the CI
system will check out a fresh copy of the application and run all the tests. It’s
a simple way to ensure that accidental breakages get immediate attention. You
can also set up your CI system so that your customers can use it to play with
the bleeding-edge version of your application. This kind of transparency is a
great way of ensuring that your project isn’t going off the tracks.
Editors
We write our Rails programs using a programmer’s editor. We’ve found over the
years that different editors work best with different languages and environ-
ments. For example, Dave originally wrote this chapter using Emacs, because
he thinks that its Filladapt mode is unsurpassed when it comes to neatly for-
matting XML as he types. Sam updated the chapter using VIM. But many
think that neither Emacs nor VIM are ideal for Rails development and prefer
to use TextMate. Although the choice of editor is a personal one, here are some
suggestions of features to look for in a Rails editor:
• Support for syntax highlighting of Ruby and HTML. Ideally support for
.erb files (a Rails file format that embeds Ruby snippets within HTML).
• Support of automatic indentation and reindentation of Ruby source. This
is more than an aesthetic feature: having an editor indent your program
as you type is the best way of spotting bad nesting in your code. Being
able to reindent is important when you refactor your code and move stuff.
3. So-called tab completion is standard on Unix shells such as Bash and zsh. It allows you to type
the first few characters of a filename, hit Tab , and have the shell look for and complete the name
based on matching files. This behavior is also available by default in the Windows XP command
shell. You can enable this behavior in older versions of Windows using the freely available TweakUI
power toy from Microsoft.
Report erratum
this copy is (P1.0 printing, March 2009)
DEVELOPMENT ENVIRONMENTS 38
Where’s My IDE?
If you’re coming to Ruby and Rails from languages such as C# and Java, you
may be wondering about IDEs. After all, we all know that it’s impossible to
code modern applications without at least 100MB of IDE supporting our every
keystroke. For you enlightened ones, here’s the point in the book where we rec-
ommend you sit down—ideally propped up on each side by a pile of frame-
work references and 1,000-page Made Easy books.
There are no fully fledged IDEs for Ruby or Rails (although some environments
come close). Instead, most Rails developers use plain old editors. And it turns
out that this isn’t as much of a problem as you might think. With other, less
expressive languages, programmers rely on IDEs to do much of the grunt work
for them: IDEs do code generation, assist with navigation, and compile incre-
mentally to give early warning of errors.
With Ruby, however, much of this support just isn’t necessary. Editors such as
TextMate give you 90 percent of what you’d get from an IDE but are far lighter
weight. Just about the only useful IDE facility that’s missing is refactoring sup-
port.∗
∗. We prefer using one editor for everything. Others use specialized editors for creating
application code vs. (say) HTML layouts. For the latter, look for plug-ins for popular tools
such as Dreamweaver.
(TextMate’s ability to reindent when it pastes code from the clipboard is
very convenient.)
• Support for insertion of common Ruby and Rails constructs. You’ll be
writing lots of short methods, and if the IDE creates method skeletons
with a keystroke or two, you can concentrate on the interesting stuff
inside.
• Good file navigation. As you’ll see, Rails applications are spread across
many files.4
You need an environment that helps you navigate quickly
between these. You’ll add a line to a controller to load up a value, switch
to the view to add a line to display it, and then switch to the test to
verify you did it all right. Something like Notepad, where you traverse
a File Open dialog box to select each file to edit, just won’t cut it. We
prefer a combination of a tree view of files in a sidebar, a small set of
keystrokes that help us find a file (or files) in a directory tree by name,
and some built-in smarts that know how to navigate (say) between a
controller action and the corresponding view.
4. A newly created Rails application enters the world containing forty-eight files spread across
thirty-seven directories. That’s before you’ve written a thing....
Report erratum
this copy is (P1.0 printing, March 2009)
DEVELOPMENT ENVIRONMENTS 39
• Name completion. Names in Rails tend to be long. A nice editor will let
you type the first few characters and then suggest possible completions
to you at the touch of a key.
We hesitate to recommend specific editors because we’ve used only a few in
earnest and we’ll undoubtedly leave someone’s favorite editor off the list. Nev-
ertheless, to help you get started with something other than Notepad, here are
some suggestions:
• The Ruby and Rails editor of choice on Mac OS X is TextMate (http://
macromates.com/).
• XCode 3.0 on Mac OS X has an Organizer that provides much of what
you might need. A tutorial that will get you started with Rails on Leopard
is available at http://developer.apple.com/tools/developonrailsleopard.html.
• For those who would otherwise like to use TextMate but happen to be
using Windows, E-TextEditor (http://e-texteditor.com/) provides “The Power
of TextMate on Windows.”
• Aptana RadRails (http://www.aptana.com/rails/) is an integrated Rails
development environment that runs in Aptana Studio and Eclipse. It
runs on Windows, Mac OS X, and Linux. It won an award for being the
best open source developer tool based on Eclipse in 2006, and Aptana
became the home for the project in 2007.
• NetBeans IDE 6.5 (http://www.netbeans.org/features/ruby/index.html) sup-
ports Windows, Mac OS X, Solaris, and Linux. It’s available in a down-
load bundle with Ruby support or as a Ruby pack that can be down-
loaded later. In addition to specific support for Rails 2.0, Rake targets,
and database migrations, it supports a Rails code generator graphical
wizard and quick navigation from a Rails action to its corresponding view.
• jEdit (http://www.jedit.org/) is a fully featured editor with support for Ruby.
It has extensive plug-in support.
• Komodo (http://www.activestate.com/Products/Komodo/) is ActiveState’s IDE
for dynamic languages, including Ruby.
• Arachno Ruby (http://www.ruby-ide.com/ruby/ruby_ide_and_ruby_editor.php)
is a commercial IDE for Ruby.
Ask experienced developers who use your kind of operating system which edi-
tor they use. Spend a week or so trying alternatives before settling in. And,
once you’ve chosen an editor, make it a point of pride to learn some new fea-
ture every day.
Report erratum
this copy is (P1.0 printing, March 2009)
RAILS AND DATABASES 40
Creating Your Own Rails API Documentation
You can create your own local version of the consolidated Rails API docu-
mentation. Just type the following commands at a command prompt (remem-
bering to start the command window in your Rails environment if you’re using
InstantRails or Locomotive):
rails_apps> rails dummy_app
rails_apps> cd dummy_app
dummy_app> rake rails:freeze:gems
dummy_app> rake doc:rails
The last step takes a while. When it finishes, you’ll have the Rails API documen-
tation in a directory tree starting at doc/api. We suggest moving this folder to
your desktop and then deleting the dummy_app tree.
To view the Rails API documentation, open the location doc/api/index.html with
your browser.
The Desktop
We’re not going to tell you how to organize your desktop while working with
Rails, but we will describe what we do.
Most of the time, we’re writing code, running tests, and poking at an appli-
cation in a browser. So, our main development desktop has an editor window
and a browser window permanently open. We also want to keep an eye on
the logging that’s generated by the application, so we keep a terminal window
open. In it, we use tail -f to scroll the contents of the log file as it’s updated. We
normally run this window with a very small font so it takes up less space—if
we see something interesting flash by, we zoom it up to investigate.
We also need access to the Rails API documentation, which we view in a
browser. In the introduction, we talked about using the gem server5
command
to run a local web server containing the Rails documentation. This is conve-
nient, but it unfortunately splits the Rails documentation across a number of
separate documentation trees. If you’re online, you can use http://api.rubyonrails.
org to see a consolidated view of all the Rails documentation in one place.
3.7 Rails and Databases
The examples in this book were written using SQLite 3 (version 3.4.0 or there-
abouts). If you want to follow along with our code, it’s probably simplest if you
use SQLite 3 too. If you decide to use something else, it won’t be a major prob-
5. For releases of RubyGems prior to 0.9.5, use the command gem server.
Report erratum
this copy is (P1.0 printing, March 2009)
RAILS AND DATABASES 41
Database Passwords
Here’s a sentence that may well prove to be controversial: you always want to
set a password on your production database. However, most Rails developers
don’t seem to bother doing it on their development databases. This isn’t an
issue for SQLite 3, but it may be an issue with databases such as MySQL, partic-
ularly if you go even further down the lazy road and just use the default MySQL
root user when in development too.
Is this dangerous? Some folks say so, but the average development machine
is (or should be) behind a firewall. And, with MySQL, you can go a step fur-
ther and disable remote access to the database by setting the skip-networking
option. So, in this book, we’ll assume you’ve gone with the flow. If instead
you’ve created special database users and/or set passwords, you’ll need to
adjust your connection parameters and the commands you type (for exam-
ple, adding the -p option to MySQL commands if you have a password set).
For some online notes on creating secure MySQL installations for production,
take a look at the “Securing MySQL: Step-by-Step” article at Security Focus
(http://www.securityfocus.com/infocus/1726).
lem. You may have to make minor adjustments to any explicit SQL in our code,
but Rails pretty much eliminates database-specific SQL from applications.
If you want to connect to a database other than SQLite 3, Rails also works
with DB2, MySQL, Oracle, Postgres, Firebird, and SQL Server. For all but
SQLite 3, you’ll need to install a database driver, a library that Rails can use
to connect to and use your database engine. This section contains the links
and instructions to get that done.
The database drivers are all written in C and are primarily distributed in
source form. If you don’t want to bother building a driver from source, take a
careful look at the driver’s website. Many times you’ll find that the author also
distributes binary versions.
If you can’t find a binary version or if you’d rather build from source anyway,
you’ll need a development environment on your machine to build the library.
Under Windows, this means having a copy of Visual C++. Under Linux, you’ll
need gcc and friends (but these will likely already be installed).
Under OS X, you’ll need to install the developer tools (they come with the
operating system but aren’t installed by default). You’ll also need to install
your database driver into the correct version of Ruby. If you installed your
own copy of Ruby, bypassing the built-in one, it is important to remember to
have this version of Ruby first in your path when building and installing the
Report erratum
this copy is (P1.0 printing, March 2009)
KEEPING UP-TO-DATE 42
database driver. You can use the command which ruby to make sure you’re not
running Ruby from /usr/bin.
The following are the available database adapters and the links to their respec-
tive home pages:
DB2 http://raa.ruby-lang.org/project/ruby-db2 or http://rubyforge.org/projects/rubyibm
Firebird http://rubyforge.org/projects/fireruby/
MySQL http://www.tmtm.org/en/mysql/ruby
Oracle http://rubyforge.org/projects/ruby-oci8
Postgres http://rubyforge.org/projects/ruby-pg
SQL Server http://github.com/rails-sqlserver
SQLite http://rubyforge.org/projects/sqlite-ruby
A pure-Ruby version of the Postgres adapter is available. Download postgres-pr
from the Ruby-DBI page at http://rubyforge.org/projects/ruby-dbi.
MySQL and SQLite adapters are also available for download as RubyGems
(mysql and sqlite3-ruby, respectively).
3.8 Keeping Up-to-Date
Assuming you installed Rails using RubyGems, keeping up-to-date is relatively
easy. Issue the following command:
rubys> gem update rails
and RubyGems will automatically update your Rails installation.6
(We’ll have
more to say about updating your application in production in the Deployment
and Production chapter, starting on page 651.) RubyGems keeps previous ver-
sions of the libraries it installs. You can delete these with the following com-
mand:
rubys> gem cleanup
After installing a new version of Rails, you might also want to update the files
that Rails initially added to your applications (the JavaScript libraries it uses
for Ajax support, various scripts, and so on). You can do this by running the
following command in your application’s top-level directory:
rubys> rake rails:update
3.9 Rails and ISPs
If you’re looking to put a Rails application online in a shared hosting environ-
ment, you’ll need to find a Ruby-savvy ISP. Look for one that supports Ruby,
has the Ruby database drivers you need, and offers Phusion Passenger and/or
6. Prior versions of gems may require an --include-dependencies option.
Report erratum
this copy is (P1.0 printing, March 2009)
RAILS AND ISPS 43
a proxy setup for Mongrel. (We’ll have more to say about deploying Rails appli-
cations in Chapter 28, Deployment and Production, on page 651.)
The page http://wiki.rubyonrails.com/rails/pages/RailsWebHosts on the Rails wiki lists
some Rails-friendly ISPs.
Now that we have Rails installed, let’s use it. On to the next chapter.
Report erratum
this copy is (P1.0 printing, March 2009)
Chapter 4
Instant Gratification
Let’s write a simple application to verify we’ve got Rails snugly installed on our
machines. Along the way, we’ll get a peek at the way Rails applications work.
4.1 Creating a New Application
When you install the Rails framework, you also get a new command-line tool,
rails, which is used to construct each new Rails application that you write.
Why do we need a tool to do this? Why can’t we just hack away in our favorite
editor and create the source for our application from scratch? Well, we could
just hack. After all, a Rails application is just Ruby source code. But Rails
also does a lot of magic behind the curtain to get our applications to work
with a minimum of explicit configuration. To get this magic to work, Rails
needs to find all the various components of your application. As we’ll see later
(in Section 15.2, Directory Structure, on page 257), this means that we need
to create a specific directory structure, slotting the code we write into the
appropriate places. The rails command simply creates this directory structure
for us and populates it with some standard Rails code.
To create your first Rails application, pop open a shell window, and navigate to
a place in your filesystem where you want to create your application’s directory
structure. In our example, we’ll be creating our projects in a directory called
work. In that directory, use the rails command to create an application called
demo. Be slightly careful here—if you have an existing directory called demo,
you will be asked whether you want to overwrite any existing files.1
rubys> cd work
work> rails demo
create
create app/controllers
1. Also, if you want to specify which Rails version to use (as described in Section 3.5, Choosing a
Rails Version, on page 36), now would be the time to do so.
CREATING A NEW APPLICATION 45
create app/helpers
create app/models
: : :
create log/development.log
create log/test.log
work>
The command has created a directory named demo. Pop down into that direc-
tory, and list its contents (using ls on a Unix box or dir under Windows). You
should see a bunch of files and subdirectories:
work> cd demo
demo> ls -p
README config/ lib/ script/ vendor/
Rakefile db/ log/ test/
app/ doc/ public/ tmp/
All these directories (and the files they contain) can be intimidating to start
with, but we can ignore most of them for now. In this chapter, we’ll use only
two of them directly: the app directory, where we’ll write our application, and
the script directory, which contains some useful utility scripts.
Let’s start in the script subdirectory. One of the scripts it contains is called
server. This script starts a stand-alone web server that can run our newly cre-
ated Rails application under WEBrick.2
So, without further ado, let’s start our
demo application:
demo> ruby script/server
=> Booting WEBrick...
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2006-01-08 21:44:10] INFO WEBrick 1.3.1
[2006-01-08 21:44:10] INFO ruby 1.8.2 (2004-12-30) [powerpc-darwin8.2.0]
[2006-01-08 21:44:11] INFO WEBrick::HTTPServer#start: pid=10138 port=3000
As the last line of the startup tracing indicates, we just started a web server on
port 3000.3
We can access the application by pointing a browser at the URL
http://localhost:3000. The result is shown in Figure 4.1.
If you look at the window where you started WEBrick, you’ll see tracing show-
ing you accessing the application. We’re going to leave WEBrick running in this
console window. Later, as we write application code and run it via our browser,
2. WEBrick is a pure-Ruby web server that is distributed with Ruby 1.8.1 and later. Because it is
guaranteed to be available, Rails uses it as its development web server. However, if the Mongrel web
server is installed on your system (and Rails can find it), the script/server command will use it in
preference to WEBrick. You can force Rails to use WEBrick by providing an option to the following
command:
demo>ruby script/server webrick
3. The 0.0.0.0 part of the address means that WEBrick will accept connections on all interfaces. On
Dave’s OS X system, that means both local interfaces (127.0.0.1 and ::1) and his LAN connection.
Report erratum
this copy is (P1.0 printing, March 2009)
HELLO, RAILS! 46
Figure 4.1: Newly created Rails application
we’ll be able to use this console window to trace the incoming requests. When
the time comes to shut down your application, you can press Ctrl-C in this
window to stop WEBrick. (Don’t do that yet—we’ll be using this particular
application in a minute.)
At this point, we have a new application running, but it has none of our code
in it. Let’s rectify this situation.
4.2 Hello, Rails!
We can’t help it—we just have to write a “Hello, World!” program to try a new
system. The equivalent in Rails would be an application that sends our cheery
greeting to a browser.
As we saw in Chapter 2, The Architecture of Rails Applications, on page 22,
Rails is a Model-View-Controller framework. Rails accepts incoming requests
from a browser, decodes the request to find a controller, and calls an action
method in that controller. The controller then invokes a particular view to
Report erratum
this copy is (P1.0 printing, March 2009)
HELLO, RAILS! 47
display the results to the user. The good news is that Rails takes care of most
of the internal plumbing that links all these actions. To write our simple “Hello,
World!” application, we need code for a controller and a view. We don’t need
code for a model, because we’re not dealing with any data. Let’s start with the
controller.
In the same way that we used the rails command to create a new Rails appli-
cation, we can also use a generator script to create a new controller for our
project. This command is called generate, and it lives in the script subdirectory
of the demo project we created. So, to create a controller called Say, we make
sure we’re in the demo directory and run the script, passing in the name of
the controller we want to create:4
demo> ruby script/generate controller Say
exists app/controllers/
exists app/helpers/
create app/views/say
exists test/functional/
create app/controllers/say_controller.rb
create test/functional/say_controller_test.rb
create app/helpers/say_helper.rb
The script logs the files and directories it examines, noting when it adds new
Ruby scripts or directories to your application. For now, we’re interested in
one of these scripts and (in a minute) the new directory.
The source file we’ll be looking at is the controller. You’ll find it in the file
app/controllers/say_controller.rb. Let’s take a look at it: defining classes
֒
→ page 670
Download work/demo1/app/controllers/say_controller.rb
class SayController < ApplicationController
end
Pretty minimal, eh? SayController is an empty class that inherits from Applica-
tionController, so it automatically gets all the default controller behavior. Let’s
spice it up. We need to add some code to have our controller handle the incom-
ing request. What does this code have to do? For now, it’ll do nothing—we
simply need an empty action method. So, the next question is, what should
this method be called? And to answer this question, we need to look at the way
Rails handles requests.
Rails and Request URLs
Like any other web application, a Rails application appears to its users to be
associated with a URL. When you point your browser at that URL, you are
talking to the application code, which generates a response to you.
4. The concept of the “name of the controller” is actually more complex than you might think,
and we’ll explain it in detail in Section 15.4, Naming Conventions, on page 268. For now, let’s just
assume the controller is called Say.
Report erratum
this copy is (P1.0 printing, March 2009)
HELLO, RAILS! 48
http://pragprog.com/say/hello
1. First part of URL addresses
the application
2. then the controller (say)
3. and the action (hello)
Figure 4.2: URLs are mapped to controllers and actions.
However, the real situation is somewhat more complicated than that. Let’s
imagine that your application is available at the URL http://pragprog.com/.
The web server that is hosting your application is fairly smart about paths.
It knows that incoming requests to this URL must be talking to the applica-
tion. Anything past this in the incoming URL will not change that—the same
application will still be invoked. Any additional path information is passed to
the application, which can use it for its own internal purposes.
Rails uses the path to determine the name of the controller to use and the
name of the action to invoke on that controller.5
This is illustrated in Fig-
ure 4.2. The first part of the path is the name of the controller, and the second
part of the path is the name of the action. This is shown in Figure 4.3, on the
next page.
Our First Action
Let’s add an action called hello to our Say controller. From the discussion in the
previous section, we know that adding a hello action means creating a method
called hello in the class SayController. But what should it do? For now, it doesn’t
have to do anything. Remember that a controller’s job is to set up things so
that the view knows what to display. In our first application, there’s nothing
to set up, so an empty action will work fine. Use your favorite editor to change methods
֒
→ page 668
the file say_controller.rb in the app/controllers directory, adding the hello method
as shown and then saving the file:
Download work/demo1/app/controllers/say_controller.rb
class SayController < ApplicationController
def hello
end
end
5. Rails is fairly flexible when it comes to parsing incoming URLs. In this chapter, we describe the
default mechanism. We’ll show how to override this in Section 21.2, Routing Requests, on page 426.
Report erratum
this copy is (P1.0 printing, March 2009)
HELLO, RAILS! 49
http://pragprog.com/say/hello
class SayController
def hello
# code for hello action
end
end
Create an instance
of SayController
and invoke the action
method hello
class UserController
def hello
# code for o action
end
end
class SayController
def hello
# code for hello action
end
end
class ProductController
def hello
# code for hello action
end
end
class LoginController
def login
# code . . .
end
end
Figure 4.3: Rails routes to controllers and actions.
Now let’s try calling it. Navigate to the URL http://localhost:3000/say/hello in a
browser window. (Note that in the development environment we don’t have any
application string at the front of the path—we route directly to the controller.)
You’ll see something that looks like the following:6
It might be annoying, but the error is perfectly reasonable (apart from the
weird path). We created the controller class and the action method, but we
haven’t told Rails what to display. And that’s where the views come in. Remem-
ber when we ran the script to create the new controller? The command added
6. If instead you see a message to the effect of No route matches "/say/hello", try stopping and
restarting your server, because something you have done caused Rails to cache your configuration
information before the controller was created.
Report erratum
this copy is (P1.0 printing, March 2009)
HELLO, RAILS! 50
three files and a new directory to our application. That directory will contain
the template files for the controller’s views. In our case, we created a controller
named say, so the views will be in the directory app/views/say.
To complete our “Hello, World!” application, let’s create a template. By default,
Rails looks for templates in a file with the same name as the action it’s han-
dling. In our case, that means we need to create a file called hello.html.erb7
in
the directory app/views/say. (Why .html.erb? We’ll explain in a minute.) For now,
let’s just put some basic HTML in there:
Download work/demo1/app/views/say/hello.html.erb
<html>
<head>
<title>Hello, Rails!</title>
</head>
<body>
<h1>Hello from Rails!</h1>
</body>
</html>
Save the file hello.html.erb, and refresh your browser window. You should see
it display our friendly greeting. Notice that we didn’t have to restart the appli-
cation to see the update. During development, Rails automatically integrates
changes into the running application as you save files:
So far, we’ve added code to two files in our Rails application tree. We added
an action to the controller, and we created a template to display a page in
the browser. These files live in standard locations in the Rails hierarchy: con-
trollers go into app/controllers, and views go into subdirectories of app/views.
This is shown in Figure 4.4, on the following page.
Making It Dynamic
So far, our Rails application is pretty boring—it just displays a static page. To
make it more dynamic, let’s have it show the current time each time it displays
the page.
To do this, we need to make a change to the template file in the view—it now
needs to include the time as a string. That raises two questions. First, how
do we add dynamic content to a template? Second, where do we get the time
from?
7. In prior versions of Rails, this file would have been called hello.rhtml.
Report erratum
this copy is (P1.0 printing, March 2009)
Random documents with unrelated
content Scribd suggests to you:
HYMN.
Saints, who mourn the slumbering dead,
Look to your incarnate head!
See him mounting from the tomb,
Death and hell await their doom.—Hallelujah.
Now, on glitt’ring thrones above,
Seraphs chaunt redeeming love;
Ransom’d saints the concert join,
Echoing the hymn divine.—Hallelujah.
Borne on clouds of azure light,
Angels wing their rapid flight,
And around the bursting grave,
Welcome him, who-died to save.—Hallelujah.
Come ye rescu’d, sing his praise,
Jesus loves to hear your lays;
He who conquered hell and death,
Hears the humblest sinner’s breath.—Hallelujah.
Father, Son, and Holy Ghost!
Triune God! of saints the boast;
Let us soon amid the throng,
Join the chorus in their song.—Hallelujah.
J. C. jun.
Shortly will be published, Choice Sayings of Dying Saints,
selected from some of the best Authors.
R. Weston, Printer, Queen’s Gardens, Crosby Row, Southwark.
FOOTNOTES.
[4] Ezekiel 24.
*** END OF THE PROJECT GUTENBERG EBOOK CONSOLATION IN
LIFE AND DEATH, DERIVED FROM THE LIFE OF CHRIST ***
Updated editions will replace the previous one—the old editions
will be renamed.
Creating the works from print editions not protected by U.S.
copyright law means that no one owns a United States
copyright in these works, so the Foundation (and you!) can copy
and distribute it in the United States without permission and
without paying copyright royalties. Special rules, set forth in the
General Terms of Use part of this license, apply to copying and
distributing Project Gutenberg™ electronic works to protect the
PROJECT GUTENBERG™ concept and trademark. Project
Gutenberg is a registered trademark, and may not be used if
you charge for an eBook, except by following the terms of the
trademark license, including paying royalties for use of the
Project Gutenberg trademark. If you do not charge anything for
copies of this eBook, complying with the trademark license is
very easy. You may use this eBook for nearly any purpose such
as creation of derivative works, reports, performances and
research. Project Gutenberg eBooks may be modified and
printed and given away—you may do practically ANYTHING in
the United States with eBooks not protected by U.S. copyright
law. Redistribution is subject to the trademark license, especially
commercial redistribution.
START: FULL LICENSE
THE FULL PROJECT GUTENBERG LICENSE
PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK
To protect the Project Gutenberg™ mission of promoting the
free distribution of electronic works, by using or distributing this
work (or any other work associated in any way with the phrase
“Project Gutenberg”), you agree to comply with all the terms of
the Full Project Gutenberg™ License available with this file or
online at www.gutenberg.org/license.
Section 1. General Terms of Use and
Redistributing Project Gutenberg™
electronic works
1.A. By reading or using any part of this Project Gutenberg™
electronic work, you indicate that you have read, understand,
agree to and accept all the terms of this license and intellectual
property (trademark/copyright) agreement. If you do not agree
to abide by all the terms of this agreement, you must cease
using and return or destroy all copies of Project Gutenberg™
electronic works in your possession. If you paid a fee for
obtaining a copy of or access to a Project Gutenberg™
electronic work and you do not agree to be bound by the terms
of this agreement, you may obtain a refund from the person or
entity to whom you paid the fee as set forth in paragraph 1.E.8.
1.B. “Project Gutenberg” is a registered trademark. It may only
be used on or associated in any way with an electronic work by
people who agree to be bound by the terms of this agreement.
There are a few things that you can do with most Project
Gutenberg™ electronic works even without complying with the
full terms of this agreement. See paragraph 1.C below. There
are a lot of things you can do with Project Gutenberg™
electronic works if you follow the terms of this agreement and
help preserve free future access to Project Gutenberg™
electronic works. See paragraph 1.E below.
1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright
law in the United States and you are located in the United
States, we do not claim a right to prevent you from copying,
distributing, performing, displaying or creating derivative works
based on the work as long as all references to Project
Gutenberg are removed. Of course, we hope that you will
support the Project Gutenberg™ mission of promoting free
access to electronic works by freely sharing Project Gutenberg™
works in compliance with the terms of this agreement for
keeping the Project Gutenberg™ name associated with the
work. You can easily comply with the terms of this agreement
by keeping this work in the same format with its attached full
Project Gutenberg™ License when you share it without charge
with others.
1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside
the United States, check the laws of your country in addition to
the terms of this agreement before downloading, copying,
displaying, performing, distributing or creating derivative works
based on this work or any other Project Gutenberg™ work. The
Foundation makes no representations concerning the copyright
status of any work in any country other than the United States.
1.E. Unless you have removed all references to Project
Gutenberg:
1.E.1. The following sentence, with active links to, or other
immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project
Gutenberg™ work (any work on which the phrase “Project
Gutenberg” appears, or with which the phrase “Project
Gutenberg” is associated) is accessed, displayed, performed,
viewed, copied or distributed:
This eBook is for the use of anyone anywhere in the United
States and most other parts of the world at no cost and
with almost no restrictions whatsoever. You may copy it,
give it away or re-use it under the terms of the Project
Gutenberg License included with this eBook or online at
www.gutenberg.org. If you are not located in the United
States, you will have to check the laws of the country
where you are located before using this eBook.
1.E.2. If an individual Project Gutenberg™ electronic work is
derived from texts not protected by U.S. copyright law (does not
contain a notice indicating that it is posted with permission of
the copyright holder), the work can be copied and distributed to
anyone in the United States without paying any fees or charges.
If you are redistributing or providing access to a work with the
phrase “Project Gutenberg” associated with or appearing on the
work, you must comply either with the requirements of
paragraphs 1.E.1 through 1.E.7 or obtain permission for the use
of the work and the Project Gutenberg™ trademark as set forth
in paragraphs 1.E.8 or 1.E.9.
1.E.3. If an individual Project Gutenberg™ electronic work is
posted with the permission of the copyright holder, your use and
distribution must comply with both paragraphs 1.E.1 through
1.E.7 and any additional terms imposed by the copyright holder.
Additional terms will be linked to the Project Gutenberg™
License for all works posted with the permission of the copyright
holder found at the beginning of this work.
1.E.4. Do not unlink or detach or remove the full Project
Gutenberg™ License terms from this work, or any files
containing a part of this work or any other work associated with
Project Gutenberg™.
1.E.5. Do not copy, display, perform, distribute or redistribute
this electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1
with active links or immediate access to the full terms of the
Project Gutenberg™ License.
1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if
you provide access to or distribute copies of a Project
Gutenberg™ work in a format other than “Plain Vanilla ASCII” or
other format used in the official version posted on the official
Project Gutenberg™ website (www.gutenberg.org), you must,
at no additional cost, fee or expense to the user, provide a copy,
a means of exporting a copy, or a means of obtaining a copy
upon request, of the work in its original “Plain Vanilla ASCII” or
other form. Any alternate format must include the full Project
Gutenberg™ License as specified in paragraph 1.E.1.
1.E.7. Do not charge a fee for access to, viewing, displaying,
performing, copying or distributing any Project Gutenberg™
works unless you comply with paragraph 1.E.8 or 1.E.9.
1.E.8. You may charge a reasonable fee for copies of or
providing access to or distributing Project Gutenberg™
electronic works provided that:
• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”
• You provide a full refund of any money paid by a user who
notifies you in writing (or by e-mail) within 30 days of receipt
that s/he does not agree to the terms of the full Project
Gutenberg™ License. You must require such a user to return or
destroy all copies of the works possessed in a physical medium
and discontinue all use of and all access to other copies of
Project Gutenberg™ works.
• You provide, in accordance with paragraph 1.F.3, a full refund of
any money paid for a work or a replacement copy, if a defect in
the electronic work is discovered and reported to you within 90
days of receipt of the work.
• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.
1.E.9. If you wish to charge a fee or distribute a Project
Gutenberg™ electronic work or group of works on different
terms than are set forth in this agreement, you must obtain
permission in writing from the Project Gutenberg Literary
Archive Foundation, the manager of the Project Gutenberg™
trademark. Contact the Foundation as set forth in Section 3
below.
1.F.
1.F.1. Project Gutenberg volunteers and employees expend
considerable effort to identify, do copyright research on,
transcribe and proofread works not protected by U.S. copyright
law in creating the Project Gutenberg™ collection. Despite these
efforts, Project Gutenberg™ electronic works, and the medium
on which they may be stored, may contain “Defects,” such as,
but not limited to, incomplete, inaccurate or corrupt data,
transcription errors, a copyright or other intellectual property
infringement, a defective or damaged disk or other medium, a
computer virus, or computer codes that damage or cannot be
read by your equipment.
1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except
for the “Right of Replacement or Refund” described in
paragraph 1.F.3, the Project Gutenberg Literary Archive
Foundation, the owner of the Project Gutenberg™ trademark,
and any other party distributing a Project Gutenberg™ electronic
work under this agreement, disclaim all liability to you for
damages, costs and expenses, including legal fees. YOU AGREE
THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT
EXCEPT THOSE PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE
THAT THE FOUNDATION, THE TRADEMARK OWNER, AND ANY
DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE LIABLE
TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL,
PUNITIVE OR INCIDENTAL DAMAGES EVEN IF YOU GIVE
NOTICE OF THE POSSIBILITY OF SUCH DAMAGE.
1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you
discover a defect in this electronic work within 90 days of
receiving it, you can receive a refund of the money (if any) you
paid for it by sending a written explanation to the person you
received the work from. If you received the work on a physical
medium, you must return the medium with your written
explanation. The person or entity that provided you with the
defective work may elect to provide a replacement copy in lieu
of a refund. If you received the work electronically, the person
or entity providing it to you may choose to give you a second
opportunity to receive the work electronically in lieu of a refund.
If the second copy is also defective, you may demand a refund
in writing without further opportunities to fix the problem.
1.F.4. Except for the limited right of replacement or refund set
forth in paragraph 1.F.3, this work is provided to you ‘AS-IS’,
WITH NO OTHER WARRANTIES OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.
1.F.5. Some states do not allow disclaimers of certain implied
warranties or the exclusion or limitation of certain types of
damages. If any disclaimer or limitation set forth in this
agreement violates the law of the state applicable to this
agreement, the agreement shall be interpreted to make the
maximum disclaimer or limitation permitted by the applicable
state law. The invalidity or unenforceability of any provision of
this agreement shall not void the remaining provisions.
1.F.6. INDEMNITY - You agree to indemnify and hold the
Foundation, the trademark owner, any agent or employee of the
Foundation, anyone providing copies of Project Gutenberg™
electronic works in accordance with this agreement, and any
volunteers associated with the production, promotion and
distribution of Project Gutenberg™ electronic works, harmless
from all liability, costs and expenses, including legal fees, that
arise directly or indirectly from any of the following which you
do or cause to occur: (a) distribution of this or any Project
Gutenberg™ work, (b) alteration, modification, or additions or
deletions to any Project Gutenberg™ work, and (c) any Defect
you cause.
Section 2. Information about the Mission
of Project Gutenberg™
Project Gutenberg™ is synonymous with the free distribution of
electronic works in formats readable by the widest variety of
computers including obsolete, old, middle-aged and new
computers. It exists because of the efforts of hundreds of
volunteers and donations from people in all walks of life.
Volunteers and financial support to provide volunteers with the
assistance they need are critical to reaching Project
Gutenberg™’s goals and ensuring that the Project Gutenberg™
collection will remain freely available for generations to come. In
2001, the Project Gutenberg Literary Archive Foundation was
created to provide a secure and permanent future for Project
Gutenberg™ and future generations. To learn more about the
Project Gutenberg Literary Archive Foundation and how your
efforts and donations can help, see Sections 3 and 4 and the
Foundation information page at www.gutenberg.org.
Section 3. Information about the Project
Gutenberg Literary Archive Foundation
The Project Gutenberg Literary Archive Foundation is a non-
profit 501(c)(3) educational corporation organized under the
laws of the state of Mississippi and granted tax exempt status
by the Internal Revenue Service. The Foundation’s EIN or
federal tax identification number is 64-6221541. Contributions
to the Project Gutenberg Literary Archive Foundation are tax
deductible to the full extent permitted by U.S. federal laws and
your state’s laws.
The Foundation’s business office is located at 809 North 1500
West, Salt Lake City, UT 84116, (801) 596-1887. Email contact
links and up to date contact information can be found at the
Foundation’s website and official page at
www.gutenberg.org/contact
Section 4. Information about Donations to
the Project Gutenberg Literary Archive
Foundation
Project Gutenberg™ depends upon and cannot survive without
widespread public support and donations to carry out its mission
of increasing the number of public domain and licensed works
that can be freely distributed in machine-readable form
accessible by the widest array of equipment including outdated
equipment. Many small donations ($1 to $5,000) are particularly
important to maintaining tax exempt status with the IRS.
The Foundation is committed to complying with the laws
regulating charities and charitable donations in all 50 states of
the United States. Compliance requirements are not uniform
and it takes a considerable effort, much paperwork and many
fees to meet and keep up with these requirements. We do not
solicit donations in locations where we have not received written
confirmation of compliance. To SEND DONATIONS or determine
the status of compliance for any particular state visit
www.gutenberg.org/donate.
While we cannot and do not solicit contributions from states
where we have not met the solicitation requirements, we know
of no prohibition against accepting unsolicited donations from
donors in such states who approach us with offers to donate.
International donations are gratefully accepted, but we cannot
make any statements concerning tax treatment of donations
received from outside the United States. U.S. laws alone swamp
our small staff.
Please check the Project Gutenberg web pages for current
donation methods and addresses. Donations are accepted in a
number of other ways including checks, online payments and
credit card donations. To donate, please visit:
www.gutenberg.org/donate.
Section 5. General Information About
Project Gutenberg™ electronic works
Professor Michael S. Hart was the originator of the Project
Gutenberg™ concept of a library of electronic works that could
be freely shared with anyone. For forty years, he produced and
distributed Project Gutenberg™ eBooks with only a loose
network of volunteer support.
Project Gutenberg™ eBooks are often created from several
printed editions, all of which are confirmed as not protected by
copyright in the U.S. unless a copyright notice is included. Thus,
we do not necessarily keep eBooks in compliance with any
particular paper edition.
Most people start at our website which has the main PG search
facility: www.gutenberg.org.
This website includes information about Project Gutenberg™,
including how to make donations to the Project Gutenberg
Literary Archive Foundation, how to help produce our new
eBooks, and how to subscribe to our email newsletter to hear
about new eBooks.
back
back
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.
More than just a book-buying platform, we strive to be a bridge
connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.
Join us on a journey of knowledge exploration, passion nurturing, and
personal growth every day!
ebookbell.com

More Related Content

Similar to Agile Web Development With Rails Third Edition Third Ruby Sam (20)

Learning Rails 3 Rails from the Outside In 1st Edition Simon St. Laurent
Learning Rails 3 Rails from the Outside In 1st Edition Simon St. Laurent
tobarpaolico
 
Report-V1.5_with_comments
Report-V1.5_with_comments
Mohamed Abdelsalam
 
Tutorial
Tutorial
Luis Fabián Ortega Ruiz
 
BOOK - IBM tivoli netcool service quality manager data mediation gateway deve...
BOOK - IBM tivoli netcool service quality manager data mediation gateway deve...
Satya Harish
 
Explorations in Parallel Distributed Processing: A Handbook of Models, Progra...
Explorations in Parallel Distributed Processing: A Handbook of Models, Progra...
mustafa sarac
 
Sg247692 Websphere Accounting Chargeback For Tuam Guide
Sg247692 Websphere Accounting Chargeback For Tuam Guide
brzaaap
 
gp4
gp4
Khalil Fadhel
 
Pragmatic version control using Git 1st Edition Travis Swicegood
Pragmatic version control using Git 1st Edition Travis Swicegood
sebigokgaje
 
java web_programming
java web_programming
bachector
 
Microsoft Sharepoint 2007 Development Unleashed 1st Edition Kevin Hoffman
Microsoft Sharepoint 2007 Development Unleashed 1st Edition Kevin Hoffman
zanjokottol46
 
Db2 deployment guide
Db2 deployment guide
bupbechanhgmail
 
Programming iOS 5 2nd Edition Matt Neuburg
Programming iOS 5 2nd Edition Matt Neuburg
saertahai
 
Angular Up and Running Learning Angular Step by Step 1st Edition Shyam Seshadri
Angular Up and Running Learning Angular Step by Step 1st Edition Shyam Seshadri
maneskortyjt
 
Java
Java
Raghavendra Rao
 
Introducing Ibm Tivoli Service Level Advisor Ibm Redbooks
Introducing Ibm Tivoli Service Level Advisor Ibm Redbooks
kempaydiid
 
Download ebooks file Code in the Cloud 1st Edition Mark C. Chu-Carroll all ch...
Download ebooks file Code in the Cloud 1st Edition Mark C. Chu-Carroll all ch...
veinergiffra
 
Practical Rails Projects Experts Voice 1st Ed Alameda Eldon
Practical Rails Projects Experts Voice 1st Ed Alameda Eldon
testnihge
 
Java web programming
Java web programming
Mumbai Academisc
 
Programming Ios 4 Fundamentals Of Iphone Ipad And Ipod Touch Development 1st ...
Programming Ios 4 Fundamentals Of Iphone Ipad And Ipod Touch Development 1st ...
jungieaugi
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
tutorialsruby
 
Learning Rails 3 Rails from the Outside In 1st Edition Simon St. Laurent
Learning Rails 3 Rails from the Outside In 1st Edition Simon St. Laurent
tobarpaolico
 
BOOK - IBM tivoli netcool service quality manager data mediation gateway deve...
BOOK - IBM tivoli netcool service quality manager data mediation gateway deve...
Satya Harish
 
Explorations in Parallel Distributed Processing: A Handbook of Models, Progra...
Explorations in Parallel Distributed Processing: A Handbook of Models, Progra...
mustafa sarac
 
Sg247692 Websphere Accounting Chargeback For Tuam Guide
Sg247692 Websphere Accounting Chargeback For Tuam Guide
brzaaap
 
Pragmatic version control using Git 1st Edition Travis Swicegood
Pragmatic version control using Git 1st Edition Travis Swicegood
sebigokgaje
 
java web_programming
java web_programming
bachector
 
Microsoft Sharepoint 2007 Development Unleashed 1st Edition Kevin Hoffman
Microsoft Sharepoint 2007 Development Unleashed 1st Edition Kevin Hoffman
zanjokottol46
 
Programming iOS 5 2nd Edition Matt Neuburg
Programming iOS 5 2nd Edition Matt Neuburg
saertahai
 
Angular Up and Running Learning Angular Step by Step 1st Edition Shyam Seshadri
Angular Up and Running Learning Angular Step by Step 1st Edition Shyam Seshadri
maneskortyjt
 
Introducing Ibm Tivoli Service Level Advisor Ibm Redbooks
Introducing Ibm Tivoli Service Level Advisor Ibm Redbooks
kempaydiid
 
Download ebooks file Code in the Cloud 1st Edition Mark C. Chu-Carroll all ch...
Download ebooks file Code in the Cloud 1st Edition Mark C. Chu-Carroll all ch...
veinergiffra
 
Practical Rails Projects Experts Voice 1st Ed Alameda Eldon
Practical Rails Projects Experts Voice 1st Ed Alameda Eldon
testnihge
 
Programming Ios 4 Fundamentals Of Iphone Ipad And Ipod Touch Development 1st ...
Programming Ios 4 Fundamentals Of Iphone Ipad And Ipod Touch Development 1st ...
jungieaugi
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
tutorialsruby
 

Recently uploaded (20)

Sustainable Innovation with Immersive Learning
Sustainable Innovation with Immersive Learning
Leonel Morgado
 
How to Manage Multi Language for Invoice in Odoo 18
How to Manage Multi Language for Invoice in Odoo 18
Celine George
 
IDF 30min presentation - December 2, 2024.pptx
IDF 30min presentation - December 2, 2024.pptx
ArneeAgligar
 
SPENT QUIZ NQL JR FEST 5.0 BY SOURAV.pptx
SPENT QUIZ NQL JR FEST 5.0 BY SOURAV.pptx
Sourav Kr Podder
 
LDMMIA Spring Ending Guest Grad Student News
LDMMIA Spring Ending Guest Grad Student News
LDM & Mia eStudios
 
ABCs of Bookkeeping for Nonprofits TechSoup.pdf
ABCs of Bookkeeping for Nonprofits TechSoup.pdf
TechSoup
 
Unit 3 Poster Sketches with annotations.pptx
Unit 3 Poster Sketches with annotations.pptx
bobby205207
 
Exploring Ocean Floor Features for Middle School
Exploring Ocean Floor Features for Middle School
Marie
 
Final Sketch Designs for poster production.pptx
Final Sketch Designs for poster production.pptx
bobby205207
 
Webcrawler_Mule_AIChain_MuleSoft_Meetup_Hyderabad
Webcrawler_Mule_AIChain_MuleSoft_Meetup_Hyderabad
Veera Pallapu
 
MATERI PPT TOPIK 4 LANDASAN FILOSOFIS PENDIDIKAN
MATERI PPT TOPIK 4 LANDASAN FILOSOFIS PENDIDIKAN
aditya23173
 
BUSINESS QUIZ PRELIMS | QUIZ CLUB OF PSGCAS | 9 SEPTEMBER 2024
BUSINESS QUIZ PRELIMS | QUIZ CLUB OF PSGCAS | 9 SEPTEMBER 2024
Quiz Club of PSG College of Arts & Science
 
Chalukyas of Gujrat, Solanki Dynasty NEP.pptx
Chalukyas of Gujrat, Solanki Dynasty NEP.pptx
Dr. Ravi Shankar Arya Mahila P. G. College, Banaras Hindu University, Varanasi, India.
 
FEBA Sofia Univercity final diplian v3 GSDG 5.2025.pdf
FEBA Sofia Univercity final diplian v3 GSDG 5.2025.pdf
ChristinaFortunova
 
How to Manage Inventory Movement in Odoo 18 POS
How to Manage Inventory Movement in Odoo 18 POS
Celine George
 
Ray Dalio How Countries go Broke the Big Cycle
Ray Dalio How Countries go Broke the Big Cycle
Dadang Solihin
 
How to Manage Upselling of Subscriptions in Odoo 18
How to Manage Upselling of Subscriptions in Odoo 18
Celine George
 
Capitol Doctoral Presentation -June 2025.pptx
Capitol Doctoral Presentation -June 2025.pptx
CapitolTechU
 
LDMMIA GRAD Student Check-in Orientation Sampler
LDMMIA GRAD Student Check-in Orientation Sampler
LDM & Mia eStudios
 
How to Manage & Create a New Department in Odoo 18 Employee
How to Manage & Create a New Department in Odoo 18 Employee
Celine George
 
Sustainable Innovation with Immersive Learning
Sustainable Innovation with Immersive Learning
Leonel Morgado
 
How to Manage Multi Language for Invoice in Odoo 18
How to Manage Multi Language for Invoice in Odoo 18
Celine George
 
IDF 30min presentation - December 2, 2024.pptx
IDF 30min presentation - December 2, 2024.pptx
ArneeAgligar
 
SPENT QUIZ NQL JR FEST 5.0 BY SOURAV.pptx
SPENT QUIZ NQL JR FEST 5.0 BY SOURAV.pptx
Sourav Kr Podder
 
LDMMIA Spring Ending Guest Grad Student News
LDMMIA Spring Ending Guest Grad Student News
LDM & Mia eStudios
 
ABCs of Bookkeeping for Nonprofits TechSoup.pdf
ABCs of Bookkeeping for Nonprofits TechSoup.pdf
TechSoup
 
Unit 3 Poster Sketches with annotations.pptx
Unit 3 Poster Sketches with annotations.pptx
bobby205207
 
Exploring Ocean Floor Features for Middle School
Exploring Ocean Floor Features for Middle School
Marie
 
Final Sketch Designs for poster production.pptx
Final Sketch Designs for poster production.pptx
bobby205207
 
Webcrawler_Mule_AIChain_MuleSoft_Meetup_Hyderabad
Webcrawler_Mule_AIChain_MuleSoft_Meetup_Hyderabad
Veera Pallapu
 
MATERI PPT TOPIK 4 LANDASAN FILOSOFIS PENDIDIKAN
MATERI PPT TOPIK 4 LANDASAN FILOSOFIS PENDIDIKAN
aditya23173
 
FEBA Sofia Univercity final diplian v3 GSDG 5.2025.pdf
FEBA Sofia Univercity final diplian v3 GSDG 5.2025.pdf
ChristinaFortunova
 
How to Manage Inventory Movement in Odoo 18 POS
How to Manage Inventory Movement in Odoo 18 POS
Celine George
 
Ray Dalio How Countries go Broke the Big Cycle
Ray Dalio How Countries go Broke the Big Cycle
Dadang Solihin
 
How to Manage Upselling of Subscriptions in Odoo 18
How to Manage Upselling of Subscriptions in Odoo 18
Celine George
 
Capitol Doctoral Presentation -June 2025.pptx
Capitol Doctoral Presentation -June 2025.pptx
CapitolTechU
 
LDMMIA GRAD Student Check-in Orientation Sampler
LDMMIA GRAD Student Check-in Orientation Sampler
LDM & Mia eStudios
 
How to Manage & Create a New Department in Odoo 18 Employee
How to Manage & Create a New Department in Odoo 18 Employee
Celine George
 
Ad

Agile Web Development With Rails Third Edition Third Ruby Sam

  • 1. Agile Web Development With Rails Third Edition Third Ruby Sam download https://ebookbell.com/product/agile-web-development-with-rails- third-edition-third-ruby-sam-55258644 Explore and download more ebooks at ebookbell.com
  • 2. Here are some recommended products that we believe you will be interested in. You can click the link to download. Agile Web Development With Rails 7 2nd Edition Sam Ruby Dave Thomas https://ebookbell.com/product/agile-web-development-with-rails-7-2nd- edition-sam-ruby-dave-thomas-51380742 Agile Web Development With Rails A Pragmatic Guide Pragmatic Programmers 1st Edition Dave Thomas https://ebookbell.com/product/agile-web-development-with-rails-a- pragmatic-guide-pragmatic-programmers-1st-edition-dave-thomas-55258848 Agile Web Development With Rails 4th Edition Beta 10 Version Fourth Edition Sam Ruby https://ebookbell.com/product/agile-web-development-with-rails-4th- edition-beta-10-version-fourth-edition-sam-ruby-2031134 Agile Web Development With Rails 6 Dave Thomas David B Copeland Sam Ruby https://ebookbell.com/product/agile-web-development-with-rails-6-dave- thomas-david-b-copeland-sam-ruby-42203806
  • 3. Agile Web Development With Rails 4 For Lorinda Hartzler Sam Ruby https://ebookbell.com/product/agile-web-development-with-rails-4-for- lorinda-hartzler-sam-ruby-43141470 Agile Web Development With Rails 5 1st Edition Sam Ruby https://ebookbell.com/product/agile-web-development-with-rails-5-1st- edition-sam-ruby-5557564 Agile Web Development With Rails 51 1st Edition Sam Ruby David B Copeland https://ebookbell.com/product/agile-web-development-with-rails-51-1st- edition-sam-ruby-david-b-copeland-7037920 Agile Web Development With Rails A Pragmatic Guide Second Edition Dave Thomas https://ebookbell.com/product/agile-web-development-with-rails-a- pragmatic-guide-second-edition-dave-thomas-931576 Agile Web Development With Rails 6 Dave Thomas David B Copeland Sam Ruby https://ebookbell.com/product/agile-web-development-with-rails-6-dave- thomas-david-b-copeland-sam-ruby-42279272
  • 6. Important Information About Rails Versions This book is written for Rails 2. As this book is going to press, the current generally available gem version of Rails is 2.2.2. The code in this book has been tested against this version. The Rails core team is continuing to work on Rails. From time to time, new releases may introduce incompatibilities for applications written for prior versions of Rails, including the code in this book. Sam Ruby is tracking the changes in Rails that affect this book on our wiki at http://pragprog.wikidot.com/changes-to-rails If you’re running a later version of Rails, check out the wiki pages to see if any changes are needed to our code. To determine the version of Rails that you are running, you can issue rails -v at a command prompt. Sam, Dave, and David
  • 7. Agile Web Development with Rails Third Edition Sam Ruby Dave Thomas David Heinemeier Hansson with Leon Breedt Mike Clark James Duncan Davidson Justin Gehtland Andreas Schwarz The Pragmatic Bookshelf Raleigh, North Carolina Dallas, Texas
  • 8. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and The Pragmatic Program- mers, 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 Program- ming, 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 © 2009 The Pragmatic Programmers LLC. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, 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-16-6 ISBN-13: 978-1-9343561-6-6 Printed on acid-free paper. P1.0 printing, March 2009 Version: 2009-3-19
  • 9. Contents Preface to the Second Edition 11 Preface to the Third Edition 13 1 Introduction 14 1.1 Rails Is Agile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.2 Finding Your Way Around . . . . . . . . . . . . . . . . . . . . . 17 1.3 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Part I—Getting Started 21 2 The Architecture of Rails Applications 22 2.1 Models, Views, and Controllers . . . . . . . . . . . . . . . . . . 22 2.2 Active Record: Rails Model Support . . . . . . . . . . . . . . . . 25 2.3 Action Pack: The View and Controller . . . . . . . . . . . . . . . 29 3 Installing Rails 31 3.1 Your Shopping List . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.2 Installing on Windows . . . . . . . . . . . . . . . . . . . . . . . . 31 3.3 Installing on Mac OS X . . . . . . . . . . . . . . . . . . . . . . . 33 3.4 Installing on Linux . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.5 Choosing a Rails Version . . . . . . . . . . . . . . . . . . . . . . 36 3.6 Development Environments . . . . . . . . . . . . . . . . . . . . 36 3.7 Rails and Databases . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.8 Keeping Up-to-Date . . . . . . . . . . . . . . . . . . . . . . . . . 42 3.9 Rails and ISPs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 4 Instant Gratification 44 4.1 Creating a New Application . . . . . . . . . . . . . . . . . . . . . 44 4.2 Hello, Rails! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 4.3 Linking Pages Together . . . . . . . . . . . . . . . . . . . . . . . 57 4.4 What We Just Did . . . . . . . . . . . . . . . . . . . . . . . . . . 61
  • 10. CONTENTS 6 Part II—Building an Application 62 5 The Depot Application 63 5.1 Incremental Development . . . . . . . . . . . . . . . . . . . . . . 63 5.2 What Depot Does . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 5.3 Let’s Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 6 Task A: Product Maintenance 69 6.1 Iteration A1: Getting Something Running . . . . . . . . . . . . 69 6.2 Creating the Products Model and Maintenance Application . . 75 6.3 Iteration A2: Adding a Missing Column . . . . . . . . . . . . . . 79 6.4 Iteration A3: Validating! . . . . . . . . . . . . . . . . . . . . . . . 85 6.5 Iteration A4: Making Prettier Listings . . . . . . . . . . . . . . . 89 7 Task B: Catalog Display 95 7.1 Iteration B1: Creating the Catalog Listing . . . . . . . . . . . . 95 7.2 Iteration B2: Adding a Page Layout . . . . . . . . . . . . . . . . 99 7.3 Iteration B3: Using a Helper to Format the Price . . . . . . . . 101 7.4 Iteration B4: Linking to the Cart . . . . . . . . . . . . . . . . . . 102 8 Task C: Cart Creation 105 8.1 Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 8.2 Iteration C1: Creating a Cart . . . . . . . . . . . . . . . . . . . . 109 8.3 Iteration C2: Creating a Smarter Cart . . . . . . . . . . . . . . 112 8.4 Iteration C3: Handling Errors . . . . . . . . . . . . . . . . . . . 115 8.5 Iteration C4: Finishing the Cart . . . . . . . . . . . . . . . . . . 120 9 Task D: Add a Dash of Ajax 124 9.1 Iteration D1: Moving the Cart . . . . . . . . . . . . . . . . . . . 125 9.2 Iteration D2: Creating an Ajax-Based Cart . . . . . . . . . . . . 130 9.3 Iteration D3: Highlighting Changes . . . . . . . . . . . . . . . . 133 9.4 Iteration D4: Hiding an Empty Cart . . . . . . . . . . . . . . . . 136 9.5 Iteration D5: Degrading If Javascript Is Disabled . . . . . . . . 139 9.6 What We Just Did . . . . . . . . . . . . . . . . . . . . . . . . . . 140 10 Task E: Check Out! 142 10.1 Iteration E1: Capturing an Order . . . . . . . . . . . . . . . . . 142 11 Task F: Administration 159 11.1 Iteration F1: Adding Users . . . . . . . . . . . . . . . . . . . . . 159 11.2 Iteration F2: Logging In . . . . . . . . . . . . . . . . . . . . . . . 168 11.3 Iteration F3: Limiting Access . . . . . . . . . . . . . . . . . . . . 171 11.4 Iteration F4: Adding a Sidebar, More Administration . . . . . . 174 Report erratum this copy is (P1.0 printing, March 2009)
  • 11. CONTENTS 7 12 Task G: One Last Wafer-Thin Change 181 12.1 Generating the XML Feed . . . . . . . . . . . . . . . . . . . . . . 181 12.2 Finishing Up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 13 Task I: Internationalization 193 13.1 Iteration I1: Enabling Translation . . . . . . . . . . . . . . . . . 193 13.2 Iteration I2: Exploring Strategies for Content . . . . . . . . . . 207 14 Task T: Testing 210 14.1 Tests Baked Right In . . . . . . . . . . . . . . . . . . . . . . . . 210 14.2 Unit Testing of Models . . . . . . . . . . . . . . . . . . . . . . . . 211 14.3 Functional Testing of Controllers . . . . . . . . . . . . . . . . . 224 14.4 Integration Testing of Applications . . . . . . . . . . . . . . . . 240 14.5 Performance Testing . . . . . . . . . . . . . . . . . . . . . . . . . 249 14.6 Using Mock Objects . . . . . . . . . . . . . . . . . . . . . . . . . 253 Part III—Working with the Rails Framework 256 15 Rails in Depth 257 15.1 So, Where’s Rails? . . . . . . . . . . . . . . . . . . . . . . . . . . 257 15.2 Directory Structure . . . . . . . . . . . . . . . . . . . . . . . . . 257 15.3 Rails Configuration . . . . . . . . . . . . . . . . . . . . . . . . . 264 15.4 Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . 268 15.5 Logging in Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 15.6 Debugging Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 15.7 What’s Next . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 16 Active Support 275 16.1 Generally Available Extensions . . . . . . . . . . . . . . . . . . 275 16.2 Enumerations and Arrays . . . . . . . . . . . . . . . . . . . . . 276 16.3 Hashes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 16.4 String Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . 278 16.5 Extensions to Numbers . . . . . . . . . . . . . . . . . . . . . . . 281 16.6 Time and Date Extensions . . . . . . . . . . . . . . . . . . . . . 282 16.7 An Extension to Ruby Symbols . . . . . . . . . . . . . . . . . . 284 16.8 with_options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 16.9 Unicode Support . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 17 Migrations 291 17.1 Creating and Running Migrations . . . . . . . . . . . . . . . . . 293 17.2 Anatomy of a Migration . . . . . . . . . . . . . . . . . . . . . . . 295 17.3 Managing Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 17.4 Data Migrations . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 Report erratum this copy is (P1.0 printing, March 2009)
  • 12. CONTENTS 8 17.5 Advanced Migrations . . . . . . . . . . . . . . . . . . . . . . . . 307 17.6 When Migrations Go Bad . . . . . . . . . . . . . . . . . . . . . . 311 17.7 Schema Manipulation Outside Migrations . . . . . . . . . . . . 312 17.8 Managing Migrations . . . . . . . . . . . . . . . . . . . . . . . . 313 18 Active Record: The Basics 315 18.1 Tables and Classes . . . . . . . . . . . . . . . . . . . . . . . . . 316 18.2 Columns and Attributes . . . . . . . . . . . . . . . . . . . . . . 316 18.3 Primary Keys and ids . . . . . . . . . . . . . . . . . . . . . . . . 320 18.4 Connecting to the Database . . . . . . . . . . . . . . . . . . . . 322 18.5 Create, Read, Update, Delete (CRUD) . . . . . . . . . . . . . . . 327 18.6 Aggregation and Structured Data . . . . . . . . . . . . . . . . . 346 18.7 Miscellany . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 19 Active Record: Relationships Between Tables 357 19.1 Creating Foreign Keys . . . . . . . . . . . . . . . . . . . . . . . . 358 19.2 Specifying Relationships in Models . . . . . . . . . . . . . . . . 360 19.3 belongs_to and has_xxx Declarations . . . . . . . . . . . . . . . 362 19.4 Joining to Multiple Tables . . . . . . . . . . . . . . . . . . . . . 377 19.5 Self-referential Joins . . . . . . . . . . . . . . . . . . . . . . . . . 387 19.6 Acts As . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 19.7 When Things Get Saved . . . . . . . . . . . . . . . . . . . . . . . 392 19.8 Preloading Child Rows . . . . . . . . . . . . . . . . . . . . . . . 394 19.9 Counters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 20 Active Record: Object Life Cycle 397 20.1 Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 20.2 Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407 20.3 Advanced Attributes . . . . . . . . . . . . . . . . . . . . . . . . . 414 20.4 Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418 21 Action Controller: Routing and URLs 425 21.1 The Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425 21.2 Routing Requests . . . . . . . . . . . . . . . . . . . . . . . . . . 426 21.3 Resource-Based Routing . . . . . . . . . . . . . . . . . . . . . . 441 21.4 Testing Routing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458 22 Action Controller and Rails 461 22.1 Action Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461 22.2 Cookies and Sessions . . . . . . . . . . . . . . . . . . . . . . . . 473 22.3 Flash: Communicating Between Actions . . . . . . . . . . . . . 486 22.4 Filters and Verification . . . . . . . . . . . . . . . . . . . . . . . 488 22.5 Caching, Part One . . . . . . . . . . . . . . . . . . . . . . . . . . 496 22.6 The Problem with GET Requests . . . . . . . . . . . . . . . . . . 505 Report erratum this copy is (P1.0 printing, March 2009)
  • 13. CONTENTS 9 23 Action View 508 23.1 Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508 23.2 Using Helpers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514 23.3 Helpers for Formatting, Linking, and Pagination . . . . . . . . 515 23.4 How Forms Work . . . . . . . . . . . . . . . . . . . . . . . . . . . 523 23.5 Forms That Wrap Model Objects . . . . . . . . . . . . . . . . . . 524 23.6 Custom Form Builders . . . . . . . . . . . . . . . . . . . . . . . 537 23.7 Working with Nonmodel Fields . . . . . . . . . . . . . . . . . . . 541 23.8 Uploading Files to Rails Applications . . . . . . . . . . . . . . . 544 23.9 Layouts and Components . . . . . . . . . . . . . . . . . . . . . . 548 23.10 Caching, Part Two . . . . . . . . . . . . . . . . . . . . . . . . . . 555 23.11 Adding New Templating Systems . . . . . . . . . . . . . . . . . 560 24 The Web, v2.0 563 24.1 Prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563 24.2 Script.aculo.us . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583 24.3 RJS Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600 24.4 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 607 25 Action Mailer 609 25.1 Sending E-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609 25.2 Receiving E-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . 620 25.3 Testing E-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . 622 26 Active Resources 625 26.1 Alternatives to Active Resource . . . . . . . . . . . . . . . . . . 625 26.2 Show Me the Code! . . . . . . . . . . . . . . . . . . . . . . . . . . 628 26.3 Relationships and Collections . . . . . . . . . . . . . . . . . . . 631 26.4 Pulling It All Together . . . . . . . . . . . . . . . . . . . . . . . . 634 Part IV—Securing and Deploying Your Application 636 27 Securing Your Rails Application 637 27.1 SQL Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 637 27.2 Creating Records Directly from Form Parameters . . . . . . . 640 27.3 Don’t Trust id Parameters . . . . . . . . . . . . . . . . . . . . . 641 27.4 Don’t Expose Controller Methods . . . . . . . . . . . . . . . . . 642 27.5 Cross-Site Scripting (CSS/XSS) . . . . . . . . . . . . . . . . . . 643 27.6 Avoid Session Fixation Attacks . . . . . . . . . . . . . . . . . . 646 27.7 File Uploads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646 27.8 Don’t Store Sensitive Information in the Clear . . . . . . . . . 647 27.9 Use SSL to Transmit Sensitive Information . . . . . . . . . . . 648 27.10 Don’t Cache Authenticated Pages . . . . . . . . . . . . . . . . . 650 27.11 Knowing That It Works . . . . . . . . . . . . . . . . . . . . . . . 650 Report erratum this copy is (P1.0 printing, March 2009)
  • 14. CONTENTS 10 28 Deployment and Production 651 28.1 Starting Early . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651 28.2 How a Production Server Works . . . . . . . . . . . . . . . . . . 652 28.3 Installing Passenger . . . . . . . . . . . . . . . . . . . . . . . . . 655 28.4 Worry-Free Deployment with Capistrano . . . . . . . . . . . . . 657 28.5 Checking Up on a Deployed Application . . . . . . . . . . . . . 661 28.6 Production Application Chores . . . . . . . . . . . . . . . . . . . 662 28.7 Moving On to Launch and Beyond . . . . . . . . . . . . . . . . 664 Part V—Appendixes 665 A Introduction to Ruby 666 A.1 Ruby Is an Object-Oriented Language . . . . . . . . . . . . . . 666 A.2 Ruby Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667 A.3 Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668 A.4 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 670 A.5 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672 A.6 Arrays and Hashes . . . . . . . . . . . . . . . . . . . . . . . . . . 673 A.7 Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . 674 A.8 Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . 675 A.9 Blocks and Iterators . . . . . . . . . . . . . . . . . . . . . . . . . 675 A.10 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676 A.11 Marshaling Objects . . . . . . . . . . . . . . . . . . . . . . . . . 677 A.12 Interactive Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . 677 A.13 Ruby Idioms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677 A.14 RDoc Documentation . . . . . . . . . . . . . . . . . . . . . . . . 679 B Configuration Parameters 680 B.1 Top-Level Configuration . . . . . . . . . . . . . . . . . . . . . . . 680 B.2 Active Record Configuration . . . . . . . . . . . . . . . . . . . . 682 B.3 Action Controller Configuration . . . . . . . . . . . . . . . . . . 684 B.4 Action View Configuration . . . . . . . . . . . . . . . . . . . . . 686 B.5 Action Mailer Configuration . . . . . . . . . . . . . . . . . . . . 686 B.6 Test Case Configuration . . . . . . . . . . . . . . . . . . . . . . . 688 C Source Code 689 C.1 The Full Depot Application . . . . . . . . . . . . . . . . . . . . . 689 D Resources 727 D.1 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . 727 Index 729 Report erratum this copy is (P1.0 printing, March 2009)
  • 15. Tous les jours, à tous points de vue, je vais de mieux en mieux. Émile Coué Preface to the Second Edition It has been eighteen months since I announced the first edition of this book. It was clear before the book came out that Rails would be big, but I don’t think anyone back then realized just how significant this framework would turn out to be. In the year that followed, Rails went from strength to strength. It was used as the basis for any number of new, exciting websites. Just as significantly, large corporations (many of them household names) started to use Rails for both inward- and outward-facing applications. Rails gained critical acclaim, too. David Heinemeier Hansson, the creator of Rails, was named Hacker of the Year at OSCON. Rails won a Jolt Award as best web development tool, and the first edition of this book received a Jolt Award as best technical book. But the Rails core team didn’t just sit still, soaking up the praise. Instead, they’ve been heads-down adding new features and facilities. Rails 1.0, which came out some months after the first edition hit the streets, added features such as database migration support, as well as updated Ajax integration. Rails 1.1, released in the spring of 2006, was a blockbuster, with more than 500 changes since the previous release. Many of these changes are deeply significant. For example, RJS templates change the way that developers write Ajax-enabled applications, and the integration testing framework changes the way these applications can be tested. A lot of work has gone into extending and enhancing Active Record, which now includes polymorphic associations, join models, better caching, and a whole lot more. The time had come to update the book to reflect all this goodness. And, as I started making the changes, I realized that something else had changed. In the time since the first book was released, we’d all gained a lot more experience of just how to write a Rails application. Some stuff that seemed like a great idea didn’t work so well in practice, and other features that initially seemed peripheral turned out to be significant. And those new practices meant that the changes to the book went far deeper than I’d expected. I was no longer doing a cosmetic sweep through the text, adding a couple of new APIs. Instead, I found myself rewriting the content. Some chapters from the original have been removed, and new chapters have been added. Many of the rest have been
  • 16. PREFACE TO THE SECOND EDITION 12 completely rewritten. So, it became clear that we were looking at a second edition—basically a new book. It seems strange to be releasing a second edition at a time when the first edition is still among the best-selling programming books in the world. But Rails has changed, and we need to change this book with it. Enjoy! Dave Thomas October 2006 Report erratum this copy is (P1.0 printing, March 2009)
  • 17. Preface to the Third Edition When Dave asked me to join as a coauthor of the third edition of this book, I was thrilled. After all, it was from the first printing of the first edition of this book that I had learned Rails. Dave and I also have much in common. Although he prefers Emacs and Mac OS X and my preferences tend toward VIM and Ubuntu, we both share a love for the command line and getting our fingers dirty with code—starting with tangible examples before diving into heavy theory. Since the time the first edition was published (and, in fact, since the second edition), much has changed. Rails is now either preinstalled or packaged for easy installation on all major development platforms. Rails itself has evolved, and a number of features that were used in previous examples have been initially deprecated and subsequently removed. New features have been added, and much experience has been obtained as to what the best practices are for using Rails. As such, this book needs to adapt. Once again. Sam Ruby January 2009
  • 18. Chapter 1 Introduction Ruby on Rails is a framework that makes it easier to develop, deploy, and maintain web applications. During the months that followed its initial release, Rails went from being an unknown toy to being a worldwide phenomenon. It has won awards, and, more important, it has become the framework of choice for the implementation of a wide range of so-called Web 2.0 applications. It isn’t just trendy among hard-core hackers; many multinational companies are using Rails to create their web applications. Why is that? There seem to be many reasons. First, a large number of developers were frustrated with the technologies they were using to create web applications. It didn’t seem to matter whether they were using Java, PHP, or .NET—there was a growing sense that their job was just too damn hard. And then, suddenly, along came Rails, and Rails was easier. But easy on its own doesn’t cut it. We’re talking about professional developers writing real-world websites. They wanted to feel that the applications they were developing would stand the test of time—that they were designed and implemented using modern, professional techniques. So, these developers dug into Rails and discovered it wasn’t just a tool for hacking out sites. For example, all Rails applications are implemented using the Model-View- Controller (MVC) architecture. Java developers are used to frameworks such as Tapestry and Struts, which are based on MVC. But Rails takes MVC further: when you develop in Rails, there’s a place for each piece of code, and all the pieces of your application interact in a standard way. It’s as if you start with the skeleton of an application already prepared. Professional programmers write tests. And again, Rails delivers. All Rails appli- cations have testing support baked right in. As you add functionality to the
  • 19. CHAPTER 1. INTRODUCTION 15 code, Rails automatically creates test stubs for that functionality. The frame- work makes it easy to test applications, and as a result, Rails applications tend to get tested. Rails applications are written in Ruby, a modern, object-oriented scripting language. Ruby is concise without being unintelligibly terse—you can express ideas naturally and cleanly in Ruby code. This leads to programs that are easy to write and (just as important) are easy to read months later. Rails takes Ruby to the limit, extending it in novel ways that make a pro- grammer’s life easier. This makes our programs shorter and more readable. It also allows us to perform tasks that would normally be done in external configuration files inside the codebase instead. This makes it far easier to see what’s happening. The following code defines the model class for a project. Don’t worry about the details for now. Instead, just think about how much information is being expressed in a few lines of code. class Project < ActiveRecord::Base belongs_to :portfolio has_one :project_manager has_many :milestones has_many :deliverables, :through => :milestones validates_presence_of :name, :description validates_acceptance_of :non_disclosure_agreement validates_uniqueness_of :short_name end Developers who came to Rails also found a strong philosophical underpinning. The design of Rails was driven by a couple of key concepts: DRY and conven- tion over configuration. DRY stands for don’t repeat yourself —every piece of knowledge in a system should be expressed in just one place. Rails uses the power of Ruby to bring that to life. You’ll find very little duplication in a Rails application; you say what you need to say in one place—a place often sug- gested by the conventions of the MVC architecture—and then move on. For programmers used to other web frameworks, where a simple change to the schema could involve them in half a dozen or more code changes, this was a revelation. Convention over configuration is crucial, too. It means that Rails has sensi- ble defaults for just about every aspect of knitting together your application. Follow the conventions, and you can write a Rails application using less code than a typical Java web application uses in XML configuration. If you need to override the conventions, Rails makes that easy, too. Developers coming to Rails found something else, too. Rails is new, and the core team of developers understands the new Web. Rails isn’t playing catch-up with the new de facto web standards; it’s helping define them. And Rails makes Report erratum this copy is (P1.0 printing, March 2009)
  • 20. RAILS IS AGILE 16 it easy for developers to integrate features such as Ajax and RESTful interfaces into their code, because support is built in. (And if you’re not familiar with Ajax and REST interfaces, never fear—we’ll explain them later in the book.) Developers are worried about deployment, too. They found that with Rails you can deploy successive releases of your application to any number of servers with a single command (and roll them back equally easily should the release prove to be somewhat less than perfect). Rails was extracted from a real-world, commercial application. It turns out that the best way to create a framework is to find the central themes in a specific application and then bottle them up in a generic foundation of code. When you’re developing your Rails application, you’re starting with half of a really good application already in place. But there’s something else to Rails—something that’s hard to describe. Some- how, it just feels right. Of course, you’ll have to take our word for that until you write some Rails applications for yourself (which should be in the next 45 minutes or so...). That’s what this book is all about. 1.1 Rails Is Agile The title of this book is Agile Web Development with Rails. You may be sur- prised to discover that we don’t have explicit sections on applying agile prac- tices X, Y, and Z to Rails coding. The reason is both simple and subtle. Agility is part of the fabric of Rails. Let’s look at the values expressed in the Agile Manifesto as a set of four pref- erences:1 Agile development favors the following: • Individuals and interactions over processes and tools • Working software over comprehensive documentation • Customer collaboration over contract negotiation • Responding to change over following a plan Rails is all about individuals and interactions. There are no heavy toolsets, no complex configurations, and no elaborate processes. There are just small groups of developers, their favorite editors, and chunks of Ruby code. This leads to transparency; what the developers do is reflected immediately in what the customer sees. It’s an intrinsically interactive process. Rails doesn’t denounce documentation. Rails makes it trivially easy to cre- ate HTML documentation for your entire codebase. But the Rails development process isn’t driven by documents. You won’t find 500-page specifications at 1. http://agilemanifesto.org/. Dave Thomas was one of the seventeen authors of this document. Report erratum this copy is (P1.0 printing, March 2009)
  • 21. FINDING YOUR WAY AROUND 17 the heart of a Rails project. Instead, you’ll find a group of users and devel- opers jointly exploring their need and the possible ways of answering that need. You’ll find solutions that change as both the developers and the users become more experienced with the problems they’re trying to solve. You’ll find a framework that delivers working software early in the development cycle. This software may be rough around the edges, but it lets the users start to get a glimpse of what you’ll be delivering. In this way, Rails encourages customer collaboration. When customers see just how quickly a Rails project can respond to change, they start to trust that the team can deliver what’s required, not just what has been requested. Confrontations are replaced by “What if?” sessions. That’s all tied to the idea of being able to respond to change. The strong, almost obsessive, way that Rails honors the DRY principle means that changes to Rails applications impact a lot less code than the same changes would in other frameworks. And since Rails applications are written in Ruby, where concepts can be expressed accurately and concisely, changes tend to be localized and easy to write. The deep emphasis on both unit and functional testing, along with support for test fixtures and stubs during testing, gives developers the safety net they need when making those changes. With a good set of tests in place, changes are less nerve-racking. Rather than constantly trying to tie Rails processes to the agile principles, we’ve decided to let the framework speak for itself. As you read through the tutorial chapters, try to imagine yourself developing web applications this way: working alongside your customers and jointly determining priorities and solu- tions to problems. Then, as you read the deeper reference material in the back, see how the underlying structure of Rails can enable you to meet your cus- tomers’ needs faster and with less ceremony. One last point about agility and Rails: although it’s probably unprofessional to mention this, think how much fun the coding will be. 1.2 Finding Your Way Around The first two parts of this book are an introduction to the concepts behind Rails and an extended example—we build a simple online store. This is the place to start if you’re looking to get a feel for Rails programming. In fact, most folks seem to enjoy building the application along with the book. If you don’t want to do all that typing, you can cheat and download the source code (a compressed tar archive or a zip file).2 2. http://www.pragprog.com/titles/rails3/code.html has the links for the downloads. Report erratum this copy is (P1.0 printing, March 2009)
  • 22. FINDING YOUR WAY AROUND 18 The third part of the book, starting on page 257, is a detailed look at all the functions and facilities of Rails. This is where you’ll go to find out how to use the various Rails components and how to deploy your Rails applications efficiently and safely. Along the way, you’ll see various conventions we’ve adopted. Live Code Most of the code snippets we show come from full-length, running exam- ples that you can download. To help you find your way, if a code listing can be found in the download, there’ll be a bar above the snippet (just like the one here). Download work/demo1/app/controllers/say_controller.rb class SayController < ApplicationController def hello end end This contains the path to the code within the download. If you’re reading the PDF version of this book and your PDF viewer supports hyperlinks, you can click the bar, and the code should appear in a browser window. Some browsers (such as Safari) will mistakenly try to interpret some of the templates as HTML. If this happens, view the source of the page to see the real source code. And in some cases involving the modification of an existing file where the lines to be changed may not be immediately obvious, you will also see some helpful little triangles on the left of the lines that you will need to change. Two such lines are indicated in the previous code. Ruby Tips Although you need to know Ruby to write Rails applications, we realize that many folks reading this book will be learning both Ruby and Rails at the same time. Appendix A, on page 666, is a (very) brief introduction to the Ruby language. When we use a Ruby-specific construct for the first time, we’ll cross-reference it to that appendix. For example, this paragraph contains a gratuitous use of :name, a Ruby symbol. In the :name ֒ → page 668 margin, you’ll see an indication that symbols are explained on page 668. So, if you don’t know Ruby or if you need a quick refresher, you might want to read Appendix A, on page 666, before you go too much further. There’s a lot of code in this book.... David Says... Every now and then you’ll come across a David Says... sidebar. Here’s where David Heinemeier Hansson gives you the real scoop on some par- ticular aspect of Rails—rationales, tricks, recommendations, and more. Report erratum this copy is (P1.0 printing, March 2009)
  • 23. ACKNOWLEDGMENTS 19 Because he’s the fellow who invented Rails, these are the sections to read if you want to become a Rails pro. Joe Asks... Joe, the mythical developer, sometimes pops up to ask questions about stuff we talk about in the text. We answer these questions as we go along. This book isn’t a reference manual for Rails. We show most of the modules and most of their methods, either by example or narratively in the text, but we don’t have hundreds of pages of API listings. There’s a good reason for this—you get that documentation whenever you install Rails, and it’s guaranteed to be more up-to-date than the material in this book. If you install Rails using RubyGems (which we recommend), simply start the gem documentation server (using the command gem server), and you can access all the Rails APIs by pointing your browser at http://localhost:8808. Rails Versions This book is based on Rails 2.0. In particular, its code has been run against the Rails 2.2.2 RubyGem. Previous versions of Rails contain incompatibilities with 2.2.2, and it is more than likely that future versions will, too. 1.3 Acknowledgments You’d think that producing a third edition of a book would be easy. After all, you already have all the text. It’s just a tweak to some code here and a minor wording change there, and you’re done. You’d think.... It’s difficult to tell exactly, but our impression is that creating each edition of Agile Web Development with Rails took about as much effort as the first edi- tion. Rails is constantly evolving and, as it does, so has this book. Parts of the Depot application were rewritten several times, and all of the narrative was updated. The emphasis on REST and the addition of the deprecation mecha- nism all changed the structure of the book as what was once hot became just lukewarm. So, this book would not exist without a massive amount of help from the Ruby and Rails communities. As with the original, this book was released as a beta book: early versions were posted as PDFs, and people made comments online. And comment they did: more than 1,200 suggestions and bug reports were posted. The vast majority ended up being incorporated, making this book immeasurably more useful than it would have been. Thank you all, both for supporting the beta book program and for contributing so much valuable feedback. Report erratum this copy is (P1.0 printing, March 2009)
  • 24. ACKNOWLEDGMENTS 20 As with the first edition, the Rails core team was incredibly helpful, answering questions, checking out code fragments, and fixing bugs. A big thank you to the following: Scott Barron (htonl), Jamis Buck (minam), Thomas Fuchs (madrobby), Jeremy Kemper (bitsweat), Michael Koziarski (nzkoz), Marcel Molina Jr, (noradio), Rick Olson (technoweenie), Nicholas Seckar (Ulysses), Sam Stephenson (sam), Tobias Lütke (xal), and Florian Weber (csshsh) We’d like to thank the folks who contributed the specialized chapters to the book: Leon Breedt, Mike Clark, James Duncan Davidson, Justin Gehtland, and Andreas Schwarz. From Sam Ruby This effort has turned out to be both harder and more rewarding than I would have ever anticipated. It’s been harder in that Rails has changed so much and there has been so much to learn (in terms of Rails 2.0, in terms of SQLite 3, and also in terms of working with a different publisher, operating system, and toolset). But I can’t begin to express how much I like the beta book program— the readers who this book has attracted so far have been great, and their comments, questions, and feedback have been most appreciated. Sam Ruby January 2009 [email protected] From Dave Thomas I keep promising myself that each book will be the last, if for no other reason than each takes me away from my family for months at a time. Once again: Juliet, Zachary, and Henry—thank you for everything. Dave Thomas November 2006 [email protected] “Agile Web Development with Rails...I found it in our local bookstore, and it seemed great!” —Dave’s mum Report erratum this copy is (P1.0 printing, March 2009)
  • 26. Chapter 2 The Architecture of Rails Applications One of the interesting features of Rails is that it imposes some fairly serious constraints on how you structure your web applications. Surprisingly, these constraints make it easier to create applications—a lot easier. Let’s see why. 2.1 Models, Views, and Controllers Back in 1979, Trygve Reenskaug came up with a new architecture for develop- ing interactive applications. In his design, applications were broken into three types of components: models, views, and controllers. The model is responsible for maintaining the state of the application. Some- times this state is transient, lasting for just a couple of interactions with the user. Sometimes the state is permanent and will be stored outside the appli- cation, often in a database. A model is more than just data; it enforces all the business rules that apply to that data. For example, if a discount shouldn’t be applied to orders of less than $20, the model will enforce the constraint. This makes sense; by putting the implementation of these business rules in the model, we make sure that nothing else in the application can make our data invalid. The model acts as both a gatekeeper and a data store. The view is responsible for generating a user interface, normally based on data in the model. For example, an online store will have a list of products to be displayed on a catalog screen. This list will be accessible via the model, but it will be a view that accesses the list from the model and formats it for the end user. Although the view may present the user with various ways of inputting data, the view itself never handles incoming data. The view’s work is done once the data is displayed. There may well be many views that access the same model data, often for different purposes. In the online store, there’ll
  • 27. MODELS, VIEWS, AND CONTROLLERS 23 Database Controller View Model ! Browser sends request ! " " Controller interacts with model # # Controller invokes view $ View renders next browser screen $ Figure 2.1: The Model-View-Controller architecture be a view that displays product information on a catalog page and another set of views used by administrators to add and edit products. Controllers orchestrate the application. Controllers receive events from the outside world (normally user input), interact with the model, and display an appropriate view to the user. This triumvirate—the model, view, and controller—together form an architec- ture known as MVC. MVC is shown in abstract terms in Figure 2.1. MVC was originally intended for conventional GUI applications, where devel- opers found the separation of concerns led to far less coupling, which in turn made the code easier to write and maintain. Each concept or action was expressed in just one well-known place. Using MVC was like constructing a skyscraper with the girders already in place—it was a lot easier to hang the rest of the pieces with a structure already there. In the software world, we often ignore good ideas from the past as we rush headlong to meet the future. When developers first started producing web applications, they went back to writing monolithic programs that intermixed presentation, database access, business logic, and event handling in one big ball of code. But ideas from the past slowly crept back in, and folks started experimenting with architectures for web applications that mirrored the 20- year-old ideas in MVC. The results were frameworks such as WebObjects, Struts, and JavaServer Faces. All are based (with varying degrees of fidelity) on the ideas of MVC. Report erratum this copy is (P1.0 printing, March 2009)
  • 28. MODELS, VIEWS, AND CONTROLLERS 24 Database ! http://my.url/store/add_to_cart/123 ! " # Controller interacts with model # $ Controller invokes view %&View renders next browser screen $ Store Controller Routing Active Record Model Display Cart View % " Routing finds store controller Figure 2.2: Rails and MVC Ruby on Rails is an MVC framework, too. Rails enforces a structure for your application—you develop models, views, and controllers as separate chunks of functionality, and it knits them all together as your program executes. One of the joys of Rails is that this knitting process is based on the use of intelligent defaults so that you typically don’t need to write any external configuration metadata to make it all work. This is an example of the Rails philosophy of favoring convention over configuration. In a Rails application, an incoming request is first sent to a router, which works out where in the application the request should be sent and how the request itself should be parsed. Ultimately, this phase identifies a particular method (called an action in Rails parlance) somewhere in the controller code. The action might look at data in the request, it might interact with the model, and it might cause other actions to be invoked. Eventually the action prepares information for the view, which renders something to the user. Rails handles an incoming request as shown in Figure 2.2. In this example, the application has previously displayed a product catalog page, and the user has just clicked the Add to Cart button next to one of the products. This button links to http://my.url/store/add_to_cart/123, where add_to_cart is an action in our application and 123 is our internal id for the selected product.1 1. We cover the format of Rails URLs later in the book. However, it’s worth pointing out here that having URLs perform actions such as “add to cart” can be dangerous. For more details, see Section 22.6, The Problem with GET Requests, on page 505. Report erratum this copy is (P1.0 printing, March 2009)
  • 29. ACTIVE RECORD: RAILS MODEL SUPPORT 25 The routing component receives the incoming request and immediately picks it apart. In this simple case, it takes the first part of the path, store, as the name of the controller and the second part, add_to_cart, as the name of an action. The last part of the path, 123, is by convention extracted into an internal parameter called id. As a result of all this analysis, the router knows it has to invoke the add_to_cart method in the controller class StoreController (we’ll talk about naming conventions on page 268). The add_to_cart method handles user requests. In this case, it finds the current user’s shopping cart (which is an object managed by the model). It also asks the model to find the information for product 123. It then tells the shopping cart to add that product to itself. (See how the model is being used to keep track of all the business data? The controller tells it what to do, and the model knows how to do it.) Now that the cart includes the new product, we can show it to the user. The controller invokes the view code, but before it does, it arranges things so that the view has access to the cart object from the model. In Rails, this invocation is often implicit; again, conventions help link a particular view with a given action. That’s all there is to an MVC web application. By following a set of conven- tions and partitioning your functionality appropriately, you’ll discover that your code becomes easier to work with and your application becomes easier to extend and maintain. Seems like a good trade. If MVC is simply a question of partitioning your code a particular way, you might be wondering why you need a framework such as Ruby on Rails. The answer is straightforward: Rails handles all of the low-level housekeeping for you—all those messy details that take so long to handle by yourself—and lets you concentrate on your application’s core functionality. Let’s see how.... 2.2 Active Record: Rails Model Support In general, we’ll want our web applications to keep their information in a rela- tional database. Order-entry systems will store orders, line items, and cus- tomer details in database tables. Even applications that normally use unstruc- tured text, such as weblogs and news sites, often use databases as their back- end data store. Although it might not be immediately apparent from the SQL2 you use to access them, relational databases are actually designed around mathematical set theory. Although this is good from a conceptual point of view, it makes it difficult to combine relational databases with object-oriented (OO) program- ming languages. Objects are all about data and operations, and databases are 2. SQL, referred to by some as Structured Query Language, is the language used to query and update relational databases. Report erratum this copy is (P1.0 printing, March 2009)
  • 30. ACTIVE RECORD: RAILS MODEL SUPPORT 26 all about sets of values. Operations that are easy to express in relational terms are sometimes difficult to code in an OO system. The reverse is also true. Over time, folks have worked out ways of reconciling the relational and OO views of their corporate data. Let’s look at two different approaches. One orga- nizes your program around the database; the other organizes the database around your program. Database-centric Programming The first folks who coded against relational databases programmed in proce- dural languages such as C and COBOL. These folks typically embedded SQL directly into their code, either as strings or by using a preprocessor that con- verted SQL in their source into lower-level calls to the database engine. The integration meant that it became natural to intertwine the database logic with the overall application logic. A developer who wanted to scan through orders and update the sales tax in each order might write something exceed- ingly ugly, such as this: EXEC SQL BEGIN DECLARE SECTION; int id; float amount; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE c1 AS CURSOR FOR select id, amount from orders; while (1) { float tax; EXEC SQL WHENEVER NOT FOUND DO break; EXEC SQL FETCH c1 INTO :id, :amount; tax = calc_sales_tax(amount) EXEC SQL UPDATE orders set tax = :tax where id = :id; } EXEC SQL CLOSE c1; EXEC SQL COMMIT WORK; Scary stuff, eh? Don’t worry. We won’t be doing any of this, even though this style of programming is common in scripting languages such as Perl and PHP. It’s also available in Ruby. For example, we could use Ruby’s DBI library to produce similar-looking code (like the previous example, this one has no error checking): Method definition ֒ → page 668 def update_sales_tax update = @db.prepare("update orders set tax=? where id=?") @db.select_all("select id, amount from orders") do |id, amount| tax = calc_sales_tax(amount) update.execute(tax, id) end end Report erratum this copy is (P1.0 printing, March 2009)
  • 31. ACTIVE RECORD: RAILS MODEL SUPPORT 27 This approach is concise and straightforward and indeed is widely used. It seems like an ideal solution for small applications. However, there is a prob- lem. Intermixing business logic and database access like this can make it hard to maintain and extend the applications in the future. And you still need to know SQL just to get started on your application. Say, for example, our enlightened state government passes a new law that says we have to record the date and time that sales tax was calculated. That’s not a problem, we think. We just have to get the current time in our loop, add a column to the SQL update statement, and pass the time to the execute call. But what happens if we set the sales tax column in many different places in the application? Now we’ll need to go through and find all these places, updating each. We have duplicated code, and (if we miss a place where the column is set) we have a source of errors. In regular programming, object orientation has taught us that encapsulation solves these types of problems. We’d wrap everything to do with orders in a class; we’d have a single place to update when the regulations change. Folks have extended these ideas to database programming. The basic premise is trivially simple. We wrap access to the database behind a layer of classes. The rest of our application uses these classes and their objects—it never inter- acts with the database directly. This way we’ve encapsulated all the schema- specific stuff into a single layer and decoupled our application code from the low-level details of database access. In the case of our sales tax change, we’d simply change the class that wrapped the orders table to update the times- tamp whenever the sales tax was changed. In practice, this concept is harder to implement than it might appear. Real-life database tables are interconnected (an order might have multiple line items, for example), and we’d like to mirror this in our objects: the order object should contain a collection of line item objects. But we then start getting into issues of object navigation, performance, and data consistency. When faced with these complexities, the industry did what it always does; it invented a three-letter acronym: ORM, which stands for object-relational mapping. Rails uses ORM. Object-Relational Mapping ORM libraries map database tables to classes. If a database has a table called orders, our program will have a class named Order. Rows in this table corre- spond to objects of the class—a particular order is represented as an object of class Order. Within that object, attributes are used to get and set the individual columns. Our Order object has methods to get and set the amount, the sales tax, and so on. Report erratum this copy is (P1.0 printing, March 2009)
  • 32. ACTIVE RECORD: RAILS MODEL SUPPORT 28 In addition, the Rails classes that wrap our database tables provide a set of class-level methods that perform table-level operations. For example, we might need to find the order with a particular id. This is implemented as a class method that returns the corresponding Order object. In Ruby code, this might class method ֒ → page 670 look like this: order = Order.find(1) puts ֒ → page 668 puts "Customer #{order.customer_id}, amount=#{order.amount}" Sometimes these class-level methods return collections of objects: iterating ֒ → page 675 Order.find(:all, :conditions => "name='dave'").each do |order| puts order.amount end Finally, the objects corresponding to individual rows in a table have methods that operate on that row. Probably the most widely used is save, the operation that saves the row to the database: Order.find(:all, :conditions => "name='dave'").each do |order| order.discount = 0.5 order.save end So, an ORM layer maps tables to classes, rows to objects, and columns to attributes of those objects. Class methods are used to perform table-level oper- ations, and instance methods perform operations on the individual rows. In a typical ORM library, you supply configuration data to specify the map- pings between entities in the database and entities in the program. Program- mers using these ORM tools often find themselves creating and maintaining a boatload of XML configuration files. Active Record Active Record is the ORM layer supplied with Rails. It closely follows the stan- dard ORM model: tables map to classes, rows to objects, and columns to object attributes. It differs from most other ORM libraries in the way it is configured. By relying on convention and starting with sensible defaults, Active Record minimizes the amount of configuration that developers perform. To illustrate this, here’s a program that uses Active Record to wrap our orders table: require 'active_record' class Order < ActiveRecord::Base end order = Order.find(1) order.discount = 0.5 order.save Report erratum this copy is (P1.0 printing, March 2009)
  • 33. ACTION PACK: THE VIEW AND CONTROLLER 29 This code uses the new Order class to fetch the order with an id of 1 and modify the discount. (We’ve omitted the code that creates a database connection for now.) Active Record relieves us of the hassles of dealing with the underlying database, leaving us free to work on business logic. But Active Record does more than that. As you’ll see when we develop our shopping cart application, starting on page 63, Active Record integrates seam- lessly with the rest of the Rails framework. If a web form sends the application data related to a business object, Active Record can extract it into our model. Active Record supports sophisticated validation of model data, and if the form data fails validations, the Rails views can extract and format errors with just a single line of code. Active Record is the solid model foundation of the Rails MVC architecture. That’s why we devote three chapters to it, starting on page 315. 2.3 Action Pack: The View and Controller When you think about it, the view and controller parts of MVC are pretty intimate. The controller supplies data to the view, and the controller receives events from the pages generated by the views. Because of these interactions, support for views and controllers in Rails is bundled into a single component, Action Pack. Don’t be fooled into thinking that your application’s view code and controller code will be jumbled up just because Action Pack is a single component. Quite the contrary; Rails gives you the separation you need to write web applications with clearly demarcated code for control and presentation logic. View Support In Rails, the view is responsible for creating either all or part of a page to be displayed in a browser.3 At its simplest, a view is a chunk of HTML code that displays some fixed text. More typically you’ll want to include dynamic content created by the action method in the controller. In Rails, dynamic content is generated by templates, which come in three flavors. The most common templating scheme, called Embedded Ruby (ERb), embeds snippets of Ruby code within a view document.4 This approach is very flexible, but purists sometimes complain that it violates the spirit of MVC. By embedding code in the view, we risk adding logic that should be in the model or the controller. This complaint is largely groundless, because views contained active code even in the original MVC architectures. Maintaining a 3. Or an XML response, or an e-mail, or.... The key point is that views generate the response back to the user. 4. This approach might be familiar to web developers working with PHP or Java’s JSP technology. Report erratum this copy is (P1.0 printing, March 2009)
  • 34. ACTION PACK: THE VIEW AND CONTROLLER 30 clean separation of concerns is part of the job of the developer. (We look at HTML templates in Section 23.1, ERb Templates, on page 511.) XML Builder can also be used to construct XML documents using Ruby code— the structure of the generated XML will automatically follow the structure of the code. We discuss xml.builder templates starting on page 510. Rails also provides RJS views. These allow you to create JavaScript fragments on the server that are then executed on the browser. This is great for creating dynamic Ajax interfaces. We talk about these starting on page 600. And the Controller! The Rails controller is the logical center of your application. It coordinates the interaction between the user, the views, and the model. However, Rails handles most of this interaction behind the scenes; the code you write concentrates on application-level functionality. This makes Rails controller code remarkably easy to develop and maintain. The controller is also home to a number of important ancillary services: • It is responsible for routing external requests to internal actions. It han- dles people-friendly URLs extremely well. • It manages caching, which can give applications orders-of-magnitude performance boosts. • It manages helper modules, which extend the capabilities of the view templates without bulking up their code. • It manages sessions, giving users the impression of ongoing interaction with our applications. There’s a lot to Rails. Rather than attack it component by component, let’s roll up our sleeves and write a couple of working applications. In the next chapter, we’ll install Rails. After that, we’ll write something simple, just to make sure we have everything installed correctly. In Chapter 5, The Depot Application, on page 63, we’ll start writing something more substantial—a simple online store application. Report erratum this copy is (P1.0 printing, March 2009)
  • 35. Chapter 3 Installing Rails 3.1 Your Shopping List To get Rails running on your system, you’ll need the following: • A Ruby interpreter. Rails is written in Ruby, and you’ll be writing your applications in Ruby too. The Rails team now recommends Ruby version 1.8.7. • Ruby on Rails. This book was written using Rails version 2 (specifically the 2.2.2 Rails RubyGem).1 • Some libraries. • A database. We’re using SQLite 3 in this book. For a development machine, that’s about all you’ll need (apart from an editor, and we’ll talk about editors separately). However, if you are going to deploy your application, you will also need to install a production web server (as a minimum) along with some support code to let Rails run efficiently. We have a whole chapter devoted to this, starting on page 651, so we won’t talk about it more here. So, how do you get all this installed? It depends on your operating system.... 3.2 Installing on Windows If you’re using Windows for development, you’re in luck, because InstantRails 2.0 is a single download that contains Ruby, Rails, SQLite 3 (version 3.5.4 at the time of writing), and all the gubbins needed to make them work together. It even contains an Apache web server and the support code that lets you deploy high-performance web applications. 1. It also has been tested periodically with Edge Rails and should work there too, but given the uncertain nature of the Edge at any point in time, there are no guarantees that this will work.
  • 36. INSTALLING ON WINDOWS 32 1. Create a folder to contain the InstantRails installation. The path to the folder cannot contain any spaces (so C:Program Files would be a poor choice). 2. Visit the InstantRails website,2 and follow the link to download the latest .zip file. (It’s about 70MB, so make a pot of tea before starting if you’re on a slow connection.) Put it into the directory you created in step 1. 3. You’ll need to unzip the archive if your system doesn’t do it automatically. 4. Navigate to the InstantRails-2.0 directory, and start InstantRails by double- clicking the InstantRails icon (it’s the big red I). • If you see a pop-up asking whether it’s OK to regenerate configura- tion files, say OK . • If you see a security alert saying that Apache has been blocked by the firewall, well...we’re not going to tell you whether to block it or unblock it. For the purposes of this book, we aren’t going to be using Apache, so it doesn’t matter. The safest course of action is to say Keep Blocking . If you know what you are doing and you aren’t running IIS on your machine, you can unblock the port and use Apache later. You should see a small InstantRails window appear. You can use this to monitor and control Rails applications. However, we’ll be digging a lit- tle deeper than this, so we’ll be using a console window. To start this, click the I button in the top-left corner of the InstantRails window (the button has a black I with a red dot in the lower right). From the menu, select Rails Applications..., followed by Open Ruby Console Window. You should see a command window pop up, and you’ll be sitting in the rails_apps directory, as shown in Figure 3.1, on the next page. You can verify your versions of Ruby and Rails by typing the commands ruby -v and rails -v, respectively. At this point, you’re up and running. But, before you skip to the start of the next chapter, you should know three important facts. First, and most important, whenever you want to enter commands in a console window, you must use a console started from the InstantRails menu. Follow the same procedure we used previously (clicking the I, and so on). If you bring up a regular Windows command prompt, stuff just won’t work. (Why? Because InstantRails is self-contained—it doesn’t install itself into your global Windows environment. That means all the programs you need are not by default in the Windows path. You can, with a little fiddling, add them and then use the regular command window, but the InstantRails way seems just as easy.) 2. http://instantrails.rubyforge.org/wiki/wiki.pl Report erratum this copy is (P1.0 printing, March 2009)
  • 37. INSTALLING ON MAC OS X 33 Figure 3.1: Instant Rails—starting a console Second, at the time of this writing, InstantRails 2.0 bundles and ships Rails version 2.0.2. The examples in this book are based on Rails 2.2.2. At any time you can upgrade your version of Rails to the very latest by opening an InstantRails console and typing this: C:rails_apps> gem update --system C:rails_apps> gem update rails There is no need to upgrade your version of Ruby, because Ruby 1.8.6 will work just fine. Finally, the example sessions in this book are based on execution on a Mac. Although the ruby and rails commands are exactly the same, the Unix com- mands are different. This book uses only one Unix command: ls. The Windows equivalent is dir. OK, you Windows users are done. You can skip forward to Section 3.5, Choos- ing a Rails Version, on page 36. See you there. 3.3 Installing on Mac OS X As of OS X 10.4.6 (Tiger), Mac users have a decent Ruby installation included as standard. And OS X 10.5 (Leopard) includes Rails itself. However, this is Rails 1.2.6. So either way, you have some upgrading to do, a bit more for Tiger than for Leopard, but it’s not too difficult either way. Report erratum this copy is (P1.0 printing, March 2009)
  • 38. INSTALLING ON LINUX 34 Tiger users will also need to upgrade SQLite 3. This can be done via compiling from source (which sounds scarier than it is). You can find the instructions to do so at http://www.sqlite.org/download.html. An alternate way to install SQLite 3 is via the popular MacPorts package, which you can find at http://www.macports.org/install.php. Although the instruc- tions look a bit scary, the individual steps are pretty straightforward: run an installer, run another installer, add two lines to a file, run yet another installer, and then issue a single command. This may not turn out to be easier than compiling from source for yourself, but many find the investment to be worth it because it makes installing further packages as easy as a single command. So if you have ports installed, let’s upgrade the version of SQLite 3 on your machine: sudo port upgrade sqlite3 Both Tiger and Leopard users can use the following commands to update their system the rest of the way. If you just installed MacPorts, be sure to take heed of the important note to open a new shell and verify via the env command that your path and variable changes are in effect. If you haven’t already done so, install Apple’s XCode Developer Tools (version 3.1 or later for Leopard, 2.4.1 or later for Tiger), found at the Apple Developer Connection site or on your Mac OS X installation CDs/DVD. sudo gem update --system sudo gem install rails sudo gem update rake sudo gem install sqlite3-ruby The following step is rarely necessary, but it can be helpful if things continue to go wrong. You can verify which version of SQLite 3 your sqlite3-ruby interface is bound to by running the following as a stand-alone program, from within irb, or from within ruby script/console. require 'rubygems' require 'sqlite3' tempname = "test.sqlite#{3+rand}" db = SQLite3::Database.new(tempname) puts db.execute('select sqlite_version()') db.close File.unlink(tempname) 3.4 Installing on Linux Start with your platform’s native package management system, be it aptitude, dpkg, portage, rpm, rug, synaptic, up2date, or yum. Report erratum this copy is (P1.0 printing, March 2009)
  • 39. INSTALLING ON LINUX 35 Upgrading RubyGems There are many different ways to upgrade RubyGems. Unfortunately, depend- ing on which version of RubyGems you have installed and what distribution you are running, not all of the ways work. Be persistent. Try each of the follow- ing until you find one that works for you. • Using the gem update system: sudo gem update --system • Using the gem designed to update troublesome systems: sudo gem install rubygems-update sudo update_rubygems • Using setup.rb, which is provided with rubygems-update: sudo gem install rubygems-update cd /var/lib/gems/1.8/gems/rubygems-update-* sudo ruby setup.rb • Finally, installing from source: wget http://rubyforge.org/frs/download.php/45905/rubygems-1.3.1.tgz tar xzf rubygems-1.3.1.tgz cd rubygems-1.3.1 sudo ruby setup.rb The first step is to install the necessary dependencies. The following instruc- tions are for Ubuntu 8.10, Intrepid Ibex; you can adapt them as necessary for your installation: sudo aptitude update sudo aptitude install build-essential libopenssl-ruby sudo aptitude install ruby rubygems ruby1.8-dev libsqlite3-dev Before proceeding, it is important to verify that the version of RubyGems is at least 1.3.1. You can find out the version by issuing gem -v. How to upgrade your version of RubyGems is described in the sidebar on the current page. sudo gem install rails sudo gem install sqlite3-ruby On the last command, you will be prompted to select which gem to install for your platform. Simply select the latest (topmost) gem that contains the word ruby in parentheses, and a native extension will be built for you. You may also need to add /var/lib/gems/1.8/bin to your PATH environment vari- able. You can do this by adding a line to your .bashrc file: export PATH=/var/lib/gems/1.8/bin:$PATH Report erratum this copy is (P1.0 printing, March 2009)
  • 40. CHOOSING A RAILS VERSION 36 3.5 Choosing a Rails Version The previous instructions helped you install the latest version of Rails. But occasionally you might not want to run with that version. Perhaps a new ver- sion of Rails has come out since this book has been published, so you want to be absolutely confident that the examples that you see here exactly match the version of Rails you are running. Or perhaps you are developing on one machine but intending to deploy on another machine that contains a version of Rails that you don’t have any control over. If either of these situations applies to you, you need to be aware of a few things. For starters, you can find out all the versions of Rails you have installed using the gem command: gem list --local rails You can also verify what version of Rails you are running as the default by using the rails --version command. It should return 2.2.2 or later. Installing another version of Rails is also done via the gem command. Depend- ing on your operating system, you might need to preface the command with sudo. gem install rails --version 2.2.2 Now, having multiple versions of Rails wouldn’t do anybody any good unless there were a way to pick one. As luck would have it, there is. On any rails command, you can control which version of Rails is used by inserting the full version number surrounded by underscores before the first parameter of the command: rails _2.2.2_ --version This is particularly handy when you create a new application, because once you create an application with a specific version of Rails, it will continue to use that version of Rails—even if newer versions are installed on the system—until you decide it is time to upgrade. How to change the version of Rails that your application is using is described in the sidebar on page 264. And finally, should you decide to proceed using a version other than 2.2.2, you are not completely on your own. You can find a list of changes that will affect you at http://wiki.pragprog.com/changes-to-rails. 3.6 Development Environments The day-to-day business of writing Rails programs is pretty straightforward. Everyone works differently; here’s how we work. Report erratum this copy is (P1.0 printing, March 2009)
  • 41. DEVELOPMENT ENVIRONMENTS 37 The Command Line We do a lot of work at the command line. Although there are an increasing number of GUI tools that help generate and manage a Rails application, we find the command line is still the most powerful place to be. It’s worth spending a little while getting familiar with the command line on your operating system. Find out how to use it to edit commands that you’re typing, how to search for and edit previous commands, and how to complete the names of files and commands as you type.3 Version Control We keep all our work in a version control system (currently Git). We make a point of checking a new Rails project into Git when we create it and committing changes once we have passing tests. We normally commit to the repository many times an hour. If you’re working on a Rails project with other people, consider setting up a continuous integration (CI) system. When anyone checks in changes, the CI system will check out a fresh copy of the application and run all the tests. It’s a simple way to ensure that accidental breakages get immediate attention. You can also set up your CI system so that your customers can use it to play with the bleeding-edge version of your application. This kind of transparency is a great way of ensuring that your project isn’t going off the tracks. Editors We write our Rails programs using a programmer’s editor. We’ve found over the years that different editors work best with different languages and environ- ments. For example, Dave originally wrote this chapter using Emacs, because he thinks that its Filladapt mode is unsurpassed when it comes to neatly for- matting XML as he types. Sam updated the chapter using VIM. But many think that neither Emacs nor VIM are ideal for Rails development and prefer to use TextMate. Although the choice of editor is a personal one, here are some suggestions of features to look for in a Rails editor: • Support for syntax highlighting of Ruby and HTML. Ideally support for .erb files (a Rails file format that embeds Ruby snippets within HTML). • Support of automatic indentation and reindentation of Ruby source. This is more than an aesthetic feature: having an editor indent your program as you type is the best way of spotting bad nesting in your code. Being able to reindent is important when you refactor your code and move stuff. 3. So-called tab completion is standard on Unix shells such as Bash and zsh. It allows you to type the first few characters of a filename, hit Tab , and have the shell look for and complete the name based on matching files. This behavior is also available by default in the Windows XP command shell. You can enable this behavior in older versions of Windows using the freely available TweakUI power toy from Microsoft. Report erratum this copy is (P1.0 printing, March 2009)
  • 42. DEVELOPMENT ENVIRONMENTS 38 Where’s My IDE? If you’re coming to Ruby and Rails from languages such as C# and Java, you may be wondering about IDEs. After all, we all know that it’s impossible to code modern applications without at least 100MB of IDE supporting our every keystroke. For you enlightened ones, here’s the point in the book where we rec- ommend you sit down—ideally propped up on each side by a pile of frame- work references and 1,000-page Made Easy books. There are no fully fledged IDEs for Ruby or Rails (although some environments come close). Instead, most Rails developers use plain old editors. And it turns out that this isn’t as much of a problem as you might think. With other, less expressive languages, programmers rely on IDEs to do much of the grunt work for them: IDEs do code generation, assist with navigation, and compile incre- mentally to give early warning of errors. With Ruby, however, much of this support just isn’t necessary. Editors such as TextMate give you 90 percent of what you’d get from an IDE but are far lighter weight. Just about the only useful IDE facility that’s missing is refactoring sup- port.∗ ∗. We prefer using one editor for everything. Others use specialized editors for creating application code vs. (say) HTML layouts. For the latter, look for plug-ins for popular tools such as Dreamweaver. (TextMate’s ability to reindent when it pastes code from the clipboard is very convenient.) • Support for insertion of common Ruby and Rails constructs. You’ll be writing lots of short methods, and if the IDE creates method skeletons with a keystroke or two, you can concentrate on the interesting stuff inside. • Good file navigation. As you’ll see, Rails applications are spread across many files.4 You need an environment that helps you navigate quickly between these. You’ll add a line to a controller to load up a value, switch to the view to add a line to display it, and then switch to the test to verify you did it all right. Something like Notepad, where you traverse a File Open dialog box to select each file to edit, just won’t cut it. We prefer a combination of a tree view of files in a sidebar, a small set of keystrokes that help us find a file (or files) in a directory tree by name, and some built-in smarts that know how to navigate (say) between a controller action and the corresponding view. 4. A newly created Rails application enters the world containing forty-eight files spread across thirty-seven directories. That’s before you’ve written a thing.... Report erratum this copy is (P1.0 printing, March 2009)
  • 43. DEVELOPMENT ENVIRONMENTS 39 • Name completion. Names in Rails tend to be long. A nice editor will let you type the first few characters and then suggest possible completions to you at the touch of a key. We hesitate to recommend specific editors because we’ve used only a few in earnest and we’ll undoubtedly leave someone’s favorite editor off the list. Nev- ertheless, to help you get started with something other than Notepad, here are some suggestions: • The Ruby and Rails editor of choice on Mac OS X is TextMate (http:// macromates.com/). • XCode 3.0 on Mac OS X has an Organizer that provides much of what you might need. A tutorial that will get you started with Rails on Leopard is available at http://developer.apple.com/tools/developonrailsleopard.html. • For those who would otherwise like to use TextMate but happen to be using Windows, E-TextEditor (http://e-texteditor.com/) provides “The Power of TextMate on Windows.” • Aptana RadRails (http://www.aptana.com/rails/) is an integrated Rails development environment that runs in Aptana Studio and Eclipse. It runs on Windows, Mac OS X, and Linux. It won an award for being the best open source developer tool based on Eclipse in 2006, and Aptana became the home for the project in 2007. • NetBeans IDE 6.5 (http://www.netbeans.org/features/ruby/index.html) sup- ports Windows, Mac OS X, Solaris, and Linux. It’s available in a down- load bundle with Ruby support or as a Ruby pack that can be down- loaded later. In addition to specific support for Rails 2.0, Rake targets, and database migrations, it supports a Rails code generator graphical wizard and quick navigation from a Rails action to its corresponding view. • jEdit (http://www.jedit.org/) is a fully featured editor with support for Ruby. It has extensive plug-in support. • Komodo (http://www.activestate.com/Products/Komodo/) is ActiveState’s IDE for dynamic languages, including Ruby. • Arachno Ruby (http://www.ruby-ide.com/ruby/ruby_ide_and_ruby_editor.php) is a commercial IDE for Ruby. Ask experienced developers who use your kind of operating system which edi- tor they use. Spend a week or so trying alternatives before settling in. And, once you’ve chosen an editor, make it a point of pride to learn some new fea- ture every day. Report erratum this copy is (P1.0 printing, March 2009)
  • 44. RAILS AND DATABASES 40 Creating Your Own Rails API Documentation You can create your own local version of the consolidated Rails API docu- mentation. Just type the following commands at a command prompt (remem- bering to start the command window in your Rails environment if you’re using InstantRails or Locomotive): rails_apps> rails dummy_app rails_apps> cd dummy_app dummy_app> rake rails:freeze:gems dummy_app> rake doc:rails The last step takes a while. When it finishes, you’ll have the Rails API documen- tation in a directory tree starting at doc/api. We suggest moving this folder to your desktop and then deleting the dummy_app tree. To view the Rails API documentation, open the location doc/api/index.html with your browser. The Desktop We’re not going to tell you how to organize your desktop while working with Rails, but we will describe what we do. Most of the time, we’re writing code, running tests, and poking at an appli- cation in a browser. So, our main development desktop has an editor window and a browser window permanently open. We also want to keep an eye on the logging that’s generated by the application, so we keep a terminal window open. In it, we use tail -f to scroll the contents of the log file as it’s updated. We normally run this window with a very small font so it takes up less space—if we see something interesting flash by, we zoom it up to investigate. We also need access to the Rails API documentation, which we view in a browser. In the introduction, we talked about using the gem server5 command to run a local web server containing the Rails documentation. This is conve- nient, but it unfortunately splits the Rails documentation across a number of separate documentation trees. If you’re online, you can use http://api.rubyonrails. org to see a consolidated view of all the Rails documentation in one place. 3.7 Rails and Databases The examples in this book were written using SQLite 3 (version 3.4.0 or there- abouts). If you want to follow along with our code, it’s probably simplest if you use SQLite 3 too. If you decide to use something else, it won’t be a major prob- 5. For releases of RubyGems prior to 0.9.5, use the command gem server. Report erratum this copy is (P1.0 printing, March 2009)
  • 45. RAILS AND DATABASES 41 Database Passwords Here’s a sentence that may well prove to be controversial: you always want to set a password on your production database. However, most Rails developers don’t seem to bother doing it on their development databases. This isn’t an issue for SQLite 3, but it may be an issue with databases such as MySQL, partic- ularly if you go even further down the lazy road and just use the default MySQL root user when in development too. Is this dangerous? Some folks say so, but the average development machine is (or should be) behind a firewall. And, with MySQL, you can go a step fur- ther and disable remote access to the database by setting the skip-networking option. So, in this book, we’ll assume you’ve gone with the flow. If instead you’ve created special database users and/or set passwords, you’ll need to adjust your connection parameters and the commands you type (for exam- ple, adding the -p option to MySQL commands if you have a password set). For some online notes on creating secure MySQL installations for production, take a look at the “Securing MySQL: Step-by-Step” article at Security Focus (http://www.securityfocus.com/infocus/1726). lem. You may have to make minor adjustments to any explicit SQL in our code, but Rails pretty much eliminates database-specific SQL from applications. If you want to connect to a database other than SQLite 3, Rails also works with DB2, MySQL, Oracle, Postgres, Firebird, and SQL Server. For all but SQLite 3, you’ll need to install a database driver, a library that Rails can use to connect to and use your database engine. This section contains the links and instructions to get that done. The database drivers are all written in C and are primarily distributed in source form. If you don’t want to bother building a driver from source, take a careful look at the driver’s website. Many times you’ll find that the author also distributes binary versions. If you can’t find a binary version or if you’d rather build from source anyway, you’ll need a development environment on your machine to build the library. Under Windows, this means having a copy of Visual C++. Under Linux, you’ll need gcc and friends (but these will likely already be installed). Under OS X, you’ll need to install the developer tools (they come with the operating system but aren’t installed by default). You’ll also need to install your database driver into the correct version of Ruby. If you installed your own copy of Ruby, bypassing the built-in one, it is important to remember to have this version of Ruby first in your path when building and installing the Report erratum this copy is (P1.0 printing, March 2009)
  • 46. KEEPING UP-TO-DATE 42 database driver. You can use the command which ruby to make sure you’re not running Ruby from /usr/bin. The following are the available database adapters and the links to their respec- tive home pages: DB2 http://raa.ruby-lang.org/project/ruby-db2 or http://rubyforge.org/projects/rubyibm Firebird http://rubyforge.org/projects/fireruby/ MySQL http://www.tmtm.org/en/mysql/ruby Oracle http://rubyforge.org/projects/ruby-oci8 Postgres http://rubyforge.org/projects/ruby-pg SQL Server http://github.com/rails-sqlserver SQLite http://rubyforge.org/projects/sqlite-ruby A pure-Ruby version of the Postgres adapter is available. Download postgres-pr from the Ruby-DBI page at http://rubyforge.org/projects/ruby-dbi. MySQL and SQLite adapters are also available for download as RubyGems (mysql and sqlite3-ruby, respectively). 3.8 Keeping Up-to-Date Assuming you installed Rails using RubyGems, keeping up-to-date is relatively easy. Issue the following command: rubys> gem update rails and RubyGems will automatically update your Rails installation.6 (We’ll have more to say about updating your application in production in the Deployment and Production chapter, starting on page 651.) RubyGems keeps previous ver- sions of the libraries it installs. You can delete these with the following com- mand: rubys> gem cleanup After installing a new version of Rails, you might also want to update the files that Rails initially added to your applications (the JavaScript libraries it uses for Ajax support, various scripts, and so on). You can do this by running the following command in your application’s top-level directory: rubys> rake rails:update 3.9 Rails and ISPs If you’re looking to put a Rails application online in a shared hosting environ- ment, you’ll need to find a Ruby-savvy ISP. Look for one that supports Ruby, has the Ruby database drivers you need, and offers Phusion Passenger and/or 6. Prior versions of gems may require an --include-dependencies option. Report erratum this copy is (P1.0 printing, March 2009)
  • 47. RAILS AND ISPS 43 a proxy setup for Mongrel. (We’ll have more to say about deploying Rails appli- cations in Chapter 28, Deployment and Production, on page 651.) The page http://wiki.rubyonrails.com/rails/pages/RailsWebHosts on the Rails wiki lists some Rails-friendly ISPs. Now that we have Rails installed, let’s use it. On to the next chapter. Report erratum this copy is (P1.0 printing, March 2009)
  • 48. Chapter 4 Instant Gratification Let’s write a simple application to verify we’ve got Rails snugly installed on our machines. Along the way, we’ll get a peek at the way Rails applications work. 4.1 Creating a New Application When you install the Rails framework, you also get a new command-line tool, rails, which is used to construct each new Rails application that you write. Why do we need a tool to do this? Why can’t we just hack away in our favorite editor and create the source for our application from scratch? Well, we could just hack. After all, a Rails application is just Ruby source code. But Rails also does a lot of magic behind the curtain to get our applications to work with a minimum of explicit configuration. To get this magic to work, Rails needs to find all the various components of your application. As we’ll see later (in Section 15.2, Directory Structure, on page 257), this means that we need to create a specific directory structure, slotting the code we write into the appropriate places. The rails command simply creates this directory structure for us and populates it with some standard Rails code. To create your first Rails application, pop open a shell window, and navigate to a place in your filesystem where you want to create your application’s directory structure. In our example, we’ll be creating our projects in a directory called work. In that directory, use the rails command to create an application called demo. Be slightly careful here—if you have an existing directory called demo, you will be asked whether you want to overwrite any existing files.1 rubys> cd work work> rails demo create create app/controllers 1. Also, if you want to specify which Rails version to use (as described in Section 3.5, Choosing a Rails Version, on page 36), now would be the time to do so.
  • 49. CREATING A NEW APPLICATION 45 create app/helpers create app/models : : : create log/development.log create log/test.log work> The command has created a directory named demo. Pop down into that direc- tory, and list its contents (using ls on a Unix box or dir under Windows). You should see a bunch of files and subdirectories: work> cd demo demo> ls -p README config/ lib/ script/ vendor/ Rakefile db/ log/ test/ app/ doc/ public/ tmp/ All these directories (and the files they contain) can be intimidating to start with, but we can ignore most of them for now. In this chapter, we’ll use only two of them directly: the app directory, where we’ll write our application, and the script directory, which contains some useful utility scripts. Let’s start in the script subdirectory. One of the scripts it contains is called server. This script starts a stand-alone web server that can run our newly cre- ated Rails application under WEBrick.2 So, without further ado, let’s start our demo application: demo> ruby script/server => Booting WEBrick... => Rails application started on http://0.0.0.0:3000 => Ctrl-C to shutdown server; call with --help for options [2006-01-08 21:44:10] INFO WEBrick 1.3.1 [2006-01-08 21:44:10] INFO ruby 1.8.2 (2004-12-30) [powerpc-darwin8.2.0] [2006-01-08 21:44:11] INFO WEBrick::HTTPServer#start: pid=10138 port=3000 As the last line of the startup tracing indicates, we just started a web server on port 3000.3 We can access the application by pointing a browser at the URL http://localhost:3000. The result is shown in Figure 4.1. If you look at the window where you started WEBrick, you’ll see tracing show- ing you accessing the application. We’re going to leave WEBrick running in this console window. Later, as we write application code and run it via our browser, 2. WEBrick is a pure-Ruby web server that is distributed with Ruby 1.8.1 and later. Because it is guaranteed to be available, Rails uses it as its development web server. However, if the Mongrel web server is installed on your system (and Rails can find it), the script/server command will use it in preference to WEBrick. You can force Rails to use WEBrick by providing an option to the following command: demo>ruby script/server webrick 3. The 0.0.0.0 part of the address means that WEBrick will accept connections on all interfaces. On Dave’s OS X system, that means both local interfaces (127.0.0.1 and ::1) and his LAN connection. Report erratum this copy is (P1.0 printing, March 2009)
  • 50. HELLO, RAILS! 46 Figure 4.1: Newly created Rails application we’ll be able to use this console window to trace the incoming requests. When the time comes to shut down your application, you can press Ctrl-C in this window to stop WEBrick. (Don’t do that yet—we’ll be using this particular application in a minute.) At this point, we have a new application running, but it has none of our code in it. Let’s rectify this situation. 4.2 Hello, Rails! We can’t help it—we just have to write a “Hello, World!” program to try a new system. The equivalent in Rails would be an application that sends our cheery greeting to a browser. As we saw in Chapter 2, The Architecture of Rails Applications, on page 22, Rails is a Model-View-Controller framework. Rails accepts incoming requests from a browser, decodes the request to find a controller, and calls an action method in that controller. The controller then invokes a particular view to Report erratum this copy is (P1.0 printing, March 2009)
  • 51. HELLO, RAILS! 47 display the results to the user. The good news is that Rails takes care of most of the internal plumbing that links all these actions. To write our simple “Hello, World!” application, we need code for a controller and a view. We don’t need code for a model, because we’re not dealing with any data. Let’s start with the controller. In the same way that we used the rails command to create a new Rails appli- cation, we can also use a generator script to create a new controller for our project. This command is called generate, and it lives in the script subdirectory of the demo project we created. So, to create a controller called Say, we make sure we’re in the demo directory and run the script, passing in the name of the controller we want to create:4 demo> ruby script/generate controller Say exists app/controllers/ exists app/helpers/ create app/views/say exists test/functional/ create app/controllers/say_controller.rb create test/functional/say_controller_test.rb create app/helpers/say_helper.rb The script logs the files and directories it examines, noting when it adds new Ruby scripts or directories to your application. For now, we’re interested in one of these scripts and (in a minute) the new directory. The source file we’ll be looking at is the controller. You’ll find it in the file app/controllers/say_controller.rb. Let’s take a look at it: defining classes ֒ → page 670 Download work/demo1/app/controllers/say_controller.rb class SayController < ApplicationController end Pretty minimal, eh? SayController is an empty class that inherits from Applica- tionController, so it automatically gets all the default controller behavior. Let’s spice it up. We need to add some code to have our controller handle the incom- ing request. What does this code have to do? For now, it’ll do nothing—we simply need an empty action method. So, the next question is, what should this method be called? And to answer this question, we need to look at the way Rails handles requests. Rails and Request URLs Like any other web application, a Rails application appears to its users to be associated with a URL. When you point your browser at that URL, you are talking to the application code, which generates a response to you. 4. The concept of the “name of the controller” is actually more complex than you might think, and we’ll explain it in detail in Section 15.4, Naming Conventions, on page 268. For now, let’s just assume the controller is called Say. Report erratum this copy is (P1.0 printing, March 2009)
  • 52. HELLO, RAILS! 48 http://pragprog.com/say/hello 1. First part of URL addresses the application 2. then the controller (say) 3. and the action (hello) Figure 4.2: URLs are mapped to controllers and actions. However, the real situation is somewhat more complicated than that. Let’s imagine that your application is available at the URL http://pragprog.com/. The web server that is hosting your application is fairly smart about paths. It knows that incoming requests to this URL must be talking to the applica- tion. Anything past this in the incoming URL will not change that—the same application will still be invoked. Any additional path information is passed to the application, which can use it for its own internal purposes. Rails uses the path to determine the name of the controller to use and the name of the action to invoke on that controller.5 This is illustrated in Fig- ure 4.2. The first part of the path is the name of the controller, and the second part of the path is the name of the action. This is shown in Figure 4.3, on the next page. Our First Action Let’s add an action called hello to our Say controller. From the discussion in the previous section, we know that adding a hello action means creating a method called hello in the class SayController. But what should it do? For now, it doesn’t have to do anything. Remember that a controller’s job is to set up things so that the view knows what to display. In our first application, there’s nothing to set up, so an empty action will work fine. Use your favorite editor to change methods ֒ → page 668 the file say_controller.rb in the app/controllers directory, adding the hello method as shown and then saving the file: Download work/demo1/app/controllers/say_controller.rb class SayController < ApplicationController def hello end end 5. Rails is fairly flexible when it comes to parsing incoming URLs. In this chapter, we describe the default mechanism. We’ll show how to override this in Section 21.2, Routing Requests, on page 426. Report erratum this copy is (P1.0 printing, March 2009)
  • 53. HELLO, RAILS! 49 http://pragprog.com/say/hello class SayController def hello # code for hello action end end Create an instance of SayController and invoke the action method hello class UserController def hello # code for o action end end class SayController def hello # code for hello action end end class ProductController def hello # code for hello action end end class LoginController def login # code . . . end end Figure 4.3: Rails routes to controllers and actions. Now let’s try calling it. Navigate to the URL http://localhost:3000/say/hello in a browser window. (Note that in the development environment we don’t have any application string at the front of the path—we route directly to the controller.) You’ll see something that looks like the following:6 It might be annoying, but the error is perfectly reasonable (apart from the weird path). We created the controller class and the action method, but we haven’t told Rails what to display. And that’s where the views come in. Remem- ber when we ran the script to create the new controller? The command added 6. If instead you see a message to the effect of No route matches "/say/hello", try stopping and restarting your server, because something you have done caused Rails to cache your configuration information before the controller was created. Report erratum this copy is (P1.0 printing, March 2009)
  • 54. HELLO, RAILS! 50 three files and a new directory to our application. That directory will contain the template files for the controller’s views. In our case, we created a controller named say, so the views will be in the directory app/views/say. To complete our “Hello, World!” application, let’s create a template. By default, Rails looks for templates in a file with the same name as the action it’s han- dling. In our case, that means we need to create a file called hello.html.erb7 in the directory app/views/say. (Why .html.erb? We’ll explain in a minute.) For now, let’s just put some basic HTML in there: Download work/demo1/app/views/say/hello.html.erb <html> <head> <title>Hello, Rails!</title> </head> <body> <h1>Hello from Rails!</h1> </body> </html> Save the file hello.html.erb, and refresh your browser window. You should see it display our friendly greeting. Notice that we didn’t have to restart the appli- cation to see the update. During development, Rails automatically integrates changes into the running application as you save files: So far, we’ve added code to two files in our Rails application tree. We added an action to the controller, and we created a template to display a page in the browser. These files live in standard locations in the Rails hierarchy: con- trollers go into app/controllers, and views go into subdirectories of app/views. This is shown in Figure 4.4, on the following page. Making It Dynamic So far, our Rails application is pretty boring—it just displays a static page. To make it more dynamic, let’s have it show the current time each time it displays the page. To do this, we need to make a change to the template file in the view—it now needs to include the time as a string. That raises two questions. First, how do we add dynamic content to a template? Second, where do we get the time from? 7. In prior versions of Rails, this file would have been called hello.rhtml. Report erratum this copy is (P1.0 printing, March 2009)
  • 55. Random documents with unrelated content Scribd suggests to you:
  • 56. HYMN. Saints, who mourn the slumbering dead, Look to your incarnate head! See him mounting from the tomb, Death and hell await their doom.—Hallelujah. Now, on glitt’ring thrones above, Seraphs chaunt redeeming love; Ransom’d saints the concert join, Echoing the hymn divine.—Hallelujah. Borne on clouds of azure light, Angels wing their rapid flight, And around the bursting grave, Welcome him, who-died to save.—Hallelujah. Come ye rescu’d, sing his praise, Jesus loves to hear your lays; He who conquered hell and death, Hears the humblest sinner’s breath.—Hallelujah. Father, Son, and Holy Ghost! Triune God! of saints the boast; Let us soon amid the throng, Join the chorus in their song.—Hallelujah. J. C. jun.
  • 57. Shortly will be published, Choice Sayings of Dying Saints, selected from some of the best Authors. R. Weston, Printer, Queen’s Gardens, Crosby Row, Southwark.
  • 59. *** END OF THE PROJECT GUTENBERG EBOOK CONSOLATION IN LIFE AND DEATH, DERIVED FROM THE LIFE OF CHRIST *** Updated editions will replace the previous one—the old editions will be renamed. Creating the works from print editions not protected by U.S. copyright law means that no one owns a United States copyright in these works, so the Foundation (and you!) can copy and distribute it in the United States without permission and without paying copyright royalties. Special rules, set forth in the General Terms of Use part of this license, apply to copying and distributing Project Gutenberg™ electronic works to protect the PROJECT GUTENBERG™ concept and trademark. Project Gutenberg is a registered trademark, and may not be used if you charge for an eBook, except by following the terms of the trademark license, including paying royalties for use of the Project Gutenberg trademark. If you do not charge anything for copies of this eBook, complying with the trademark license is very easy. You may use this eBook for nearly any purpose such as creation of derivative works, reports, performances and research. Project Gutenberg eBooks may be modified and printed and given away—you may do practically ANYTHING in the United States with eBooks not protected by U.S. copyright law. Redistribution is subject to the trademark license, especially commercial redistribution. START: FULL LICENSE
  • 60. THE FULL PROJECT GUTENBERG LICENSE
  • 61. PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK To protect the Project Gutenberg™ mission of promoting the free distribution of electronic works, by using or distributing this work (or any other work associated in any way with the phrase “Project Gutenberg”), you agree to comply with all the terms of the Full Project Gutenberg™ License available with this file or online at www.gutenberg.org/license. Section 1. General Terms of Use and Redistributing Project Gutenberg™ electronic works 1.A. By reading or using any part of this Project Gutenberg™ electronic work, you indicate that you have read, understand, agree to and accept all the terms of this license and intellectual property (trademark/copyright) agreement. If you do not agree to abide by all the terms of this agreement, you must cease using and return or destroy all copies of Project Gutenberg™ electronic works in your possession. If you paid a fee for obtaining a copy of or access to a Project Gutenberg™ electronic work and you do not agree to be bound by the terms of this agreement, you may obtain a refund from the person or entity to whom you paid the fee as set forth in paragraph 1.E.8. 1.B. “Project Gutenberg” is a registered trademark. It may only be used on or associated in any way with an electronic work by people who agree to be bound by the terms of this agreement. There are a few things that you can do with most Project Gutenberg™ electronic works even without complying with the full terms of this agreement. See paragraph 1.C below. There are a lot of things you can do with Project Gutenberg™ electronic works if you follow the terms of this agreement and help preserve free future access to Project Gutenberg™ electronic works. See paragraph 1.E below.
  • 62. 1.C. The Project Gutenberg Literary Archive Foundation (“the Foundation” or PGLAF), owns a compilation copyright in the collection of Project Gutenberg™ electronic works. Nearly all the individual works in the collection are in the public domain in the United States. If an individual work is unprotected by copyright law in the United States and you are located in the United States, we do not claim a right to prevent you from copying, distributing, performing, displaying or creating derivative works based on the work as long as all references to Project Gutenberg are removed. Of course, we hope that you will support the Project Gutenberg™ mission of promoting free access to electronic works by freely sharing Project Gutenberg™ works in compliance with the terms of this agreement for keeping the Project Gutenberg™ name associated with the work. You can easily comply with the terms of this agreement by keeping this work in the same format with its attached full Project Gutenberg™ License when you share it without charge with others. 1.D. The copyright laws of the place where you are located also govern what you can do with this work. Copyright laws in most countries are in a constant state of change. If you are outside the United States, check the laws of your country in addition to the terms of this agreement before downloading, copying, displaying, performing, distributing or creating derivative works based on this work or any other Project Gutenberg™ work. The Foundation makes no representations concerning the copyright status of any work in any country other than the United States. 1.E. Unless you have removed all references to Project Gutenberg: 1.E.1. The following sentence, with active links to, or other immediate access to, the full Project Gutenberg™ License must appear prominently whenever any copy of a Project Gutenberg™ work (any work on which the phrase “Project
  • 63. Gutenberg” appears, or with which the phrase “Project Gutenberg” is associated) is accessed, displayed, performed, viewed, copied or distributed: This eBook is for the use of anyone anywhere in the United States and most other parts of the world at no cost and with almost no restrictions whatsoever. You may copy it, give it away or re-use it under the terms of the Project Gutenberg License included with this eBook or online at www.gutenberg.org. If you are not located in the United States, you will have to check the laws of the country where you are located before using this eBook. 1.E.2. If an individual Project Gutenberg™ electronic work is derived from texts not protected by U.S. copyright law (does not contain a notice indicating that it is posted with permission of the copyright holder), the work can be copied and distributed to anyone in the United States without paying any fees or charges. If you are redistributing or providing access to a work with the phrase “Project Gutenberg” associated with or appearing on the work, you must comply either with the requirements of paragraphs 1.E.1 through 1.E.7 or obtain permission for the use of the work and the Project Gutenberg™ trademark as set forth in paragraphs 1.E.8 or 1.E.9. 1.E.3. If an individual Project Gutenberg™ electronic work is posted with the permission of the copyright holder, your use and distribution must comply with both paragraphs 1.E.1 through 1.E.7 and any additional terms imposed by the copyright holder. Additional terms will be linked to the Project Gutenberg™ License for all works posted with the permission of the copyright holder found at the beginning of this work. 1.E.4. Do not unlink or detach or remove the full Project Gutenberg™ License terms from this work, or any files
  • 64. containing a part of this work or any other work associated with Project Gutenberg™. 1.E.5. Do not copy, display, perform, distribute or redistribute this electronic work, or any part of this electronic work, without prominently displaying the sentence set forth in paragraph 1.E.1 with active links or immediate access to the full terms of the Project Gutenberg™ License. 1.E.6. You may convert to and distribute this work in any binary, compressed, marked up, nonproprietary or proprietary form, including any word processing or hypertext form. However, if you provide access to or distribute copies of a Project Gutenberg™ work in a format other than “Plain Vanilla ASCII” or other format used in the official version posted on the official Project Gutenberg™ website (www.gutenberg.org), you must, at no additional cost, fee or expense to the user, provide a copy, a means of exporting a copy, or a means of obtaining a copy upon request, of the work in its original “Plain Vanilla ASCII” or other form. Any alternate format must include the full Project Gutenberg™ License as specified in paragraph 1.E.1. 1.E.7. Do not charge a fee for access to, viewing, displaying, performing, copying or distributing any Project Gutenberg™ works unless you comply with paragraph 1.E.8 or 1.E.9. 1.E.8. You may charge a reasonable fee for copies of or providing access to or distributing Project Gutenberg™ electronic works provided that: • You pay a royalty fee of 20% of the gross profits you derive from the use of Project Gutenberg™ works calculated using the method you already use to calculate your applicable taxes. The fee is owed to the owner of the Project Gutenberg™ trademark, but he has agreed to donate royalties under this paragraph to the Project Gutenberg Literary Archive Foundation. Royalty
  • 65. payments must be paid within 60 days following each date on which you prepare (or are legally required to prepare) your periodic tax returns. Royalty payments should be clearly marked as such and sent to the Project Gutenberg Literary Archive Foundation at the address specified in Section 4, “Information about donations to the Project Gutenberg Literary Archive Foundation.” • You provide a full refund of any money paid by a user who notifies you in writing (or by e-mail) within 30 days of receipt that s/he does not agree to the terms of the full Project Gutenberg™ License. You must require such a user to return or destroy all copies of the works possessed in a physical medium and discontinue all use of and all access to other copies of Project Gutenberg™ works. • You provide, in accordance with paragraph 1.F.3, a full refund of any money paid for a work or a replacement copy, if a defect in the electronic work is discovered and reported to you within 90 days of receipt of the work. • You comply with all other terms of this agreement for free distribution of Project Gutenberg™ works. 1.E.9. If you wish to charge a fee or distribute a Project Gutenberg™ electronic work or group of works on different terms than are set forth in this agreement, you must obtain permission in writing from the Project Gutenberg Literary Archive Foundation, the manager of the Project Gutenberg™ trademark. Contact the Foundation as set forth in Section 3 below. 1.F. 1.F.1. Project Gutenberg volunteers and employees expend considerable effort to identify, do copyright research on, transcribe and proofread works not protected by U.S. copyright
  • 66. law in creating the Project Gutenberg™ collection. Despite these efforts, Project Gutenberg™ electronic works, and the medium on which they may be stored, may contain “Defects,” such as, but not limited to, incomplete, inaccurate or corrupt data, transcription errors, a copyright or other intellectual property infringement, a defective or damaged disk or other medium, a computer virus, or computer codes that damage or cannot be read by your equipment. 1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the “Right of Replacement or Refund” described in paragraph 1.F.3, the Project Gutenberg Literary Archive Foundation, the owner of the Project Gutenberg™ trademark, and any other party distributing a Project Gutenberg™ electronic work under this agreement, disclaim all liability to you for damages, costs and expenses, including legal fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE THAT THE FOUNDATION, THE TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH DAMAGE. 1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a defect in this electronic work within 90 days of receiving it, you can receive a refund of the money (if any) you paid for it by sending a written explanation to the person you received the work from. If you received the work on a physical medium, you must return the medium with your written explanation. The person or entity that provided you with the defective work may elect to provide a replacement copy in lieu of a refund. If you received the work electronically, the person or entity providing it to you may choose to give you a second opportunity to receive the work electronically in lieu of a refund.
  • 67. If the second copy is also defective, you may demand a refund in writing without further opportunities to fix the problem. 1.F.4. Except for the limited right of replacement or refund set forth in paragraph 1.F.3, this work is provided to you ‘AS-IS’, WITH NO OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PURPOSE. 1.F.5. Some states do not allow disclaimers of certain implied warranties or the exclusion or limitation of certain types of damages. If any disclaimer or limitation set forth in this agreement violates the law of the state applicable to this agreement, the agreement shall be interpreted to make the maximum disclaimer or limitation permitted by the applicable state law. The invalidity or unenforceability of any provision of this agreement shall not void the remaining provisions. 1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation, the trademark owner, any agent or employee of the Foundation, anyone providing copies of Project Gutenberg™ electronic works in accordance with this agreement, and any volunteers associated with the production, promotion and distribution of Project Gutenberg™ electronic works, harmless from all liability, costs and expenses, including legal fees, that arise directly or indirectly from any of the following which you do or cause to occur: (a) distribution of this or any Project Gutenberg™ work, (b) alteration, modification, or additions or deletions to any Project Gutenberg™ work, and (c) any Defect you cause. Section 2. Information about the Mission of Project Gutenberg™
  • 68. Project Gutenberg™ is synonymous with the free distribution of electronic works in formats readable by the widest variety of computers including obsolete, old, middle-aged and new computers. It exists because of the efforts of hundreds of volunteers and donations from people in all walks of life. Volunteers and financial support to provide volunteers with the assistance they need are critical to reaching Project Gutenberg™’s goals and ensuring that the Project Gutenberg™ collection will remain freely available for generations to come. In 2001, the Project Gutenberg Literary Archive Foundation was created to provide a secure and permanent future for Project Gutenberg™ and future generations. To learn more about the Project Gutenberg Literary Archive Foundation and how your efforts and donations can help, see Sections 3 and 4 and the Foundation information page at www.gutenberg.org. Section 3. Information about the Project Gutenberg Literary Archive Foundation The Project Gutenberg Literary Archive Foundation is a non- profit 501(c)(3) educational corporation organized under the laws of the state of Mississippi and granted tax exempt status by the Internal Revenue Service. The Foundation’s EIN or federal tax identification number is 64-6221541. Contributions to the Project Gutenberg Literary Archive Foundation are tax deductible to the full extent permitted by U.S. federal laws and your state’s laws. The Foundation’s business office is located at 809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887. Email contact links and up to date contact information can be found at the Foundation’s website and official page at www.gutenberg.org/contact
  • 69. Section 4. Information about Donations to the Project Gutenberg Literary Archive Foundation Project Gutenberg™ depends upon and cannot survive without widespread public support and donations to carry out its mission of increasing the number of public domain and licensed works that can be freely distributed in machine-readable form accessible by the widest array of equipment including outdated equipment. Many small donations ($1 to $5,000) are particularly important to maintaining tax exempt status with the IRS. The Foundation is committed to complying with the laws regulating charities and charitable donations in all 50 states of the United States. Compliance requirements are not uniform and it takes a considerable effort, much paperwork and many fees to meet and keep up with these requirements. We do not solicit donations in locations where we have not received written confirmation of compliance. To SEND DONATIONS or determine the status of compliance for any particular state visit www.gutenberg.org/donate. While we cannot and do not solicit contributions from states where we have not met the solicitation requirements, we know of no prohibition against accepting unsolicited donations from donors in such states who approach us with offers to donate. International donations are gratefully accepted, but we cannot make any statements concerning tax treatment of donations received from outside the United States. U.S. laws alone swamp our small staff. Please check the Project Gutenberg web pages for current donation methods and addresses. Donations are accepted in a number of other ways including checks, online payments and
  • 70. credit card donations. To donate, please visit: www.gutenberg.org/donate. Section 5. General Information About Project Gutenberg™ electronic works Professor Michael S. Hart was the originator of the Project Gutenberg™ concept of a library of electronic works that could be freely shared with anyone. For forty years, he produced and distributed Project Gutenberg™ eBooks with only a loose network of volunteer support. Project Gutenberg™ eBooks are often created from several printed editions, all of which are confirmed as not protected by copyright in the U.S. unless a copyright notice is included. Thus, we do not necessarily keep eBooks in compliance with any particular paper edition. Most people start at our website which has the main PG search facility: www.gutenberg.org. This website includes information about Project Gutenberg™, including how to make donations to the Project Gutenberg Literary Archive Foundation, how to help produce our new eBooks, and how to subscribe to our email newsletter to hear about new eBooks.
  • 71. back
  • 72. back
  • 73. Welcome to our website – the perfect destination for book lovers and knowledge seekers. We believe that every book holds a new world, offering opportunities for learning, discovery, and personal growth. That’s why we are dedicated to bringing you a diverse collection of books, ranging from classic literature and specialized publications to self-development guides and children's books. More than just a book-buying platform, we strive to be a bridge connecting you with timeless cultural and intellectual values. With an elegant, user-friendly interface and a smart search system, you can quickly find the books that best suit your interests. Additionally, our special promotions and home delivery services help you save time and fully enjoy the joy of reading. Join us on a journey of knowledge exploration, passion nurturing, and personal growth every day! ebookbell.com