HAPPY BOOKSGIVING
Use code BOOKSGIVING during checkout to save 40%-55% on books and eBooks. Shop now.
Register your product to gain access to bonus material or receive a coupon.
The expert guide to building Ruby on Rails applications
Ruby on Rails strips complexity from the development process, enabling professional developers to focus on what matters most: delivering business value. Now, for the first time, there’s a comprehensive, authoritative guide to building production-quality software with Rails. Pioneering Rails developer Obie Fernandez and a team of experts illuminate the entire Rails API, along with the Ruby idioms, design approaches, libraries, and plug-ins that make Rails so valuable. Drawing on their unsurpassed experience, they address the real challenges development teams face, showing how to use Rails’ tools and best practices to maximize productivity and build polished applications users will enjoy.
Using detailed code examples, Obie systematically covers Rails’ key capabilities and subsystems. He presents advanced programming techniques, introduces open source libraries that facilitate easy Rails adoption, and offers important insights into testing and production deployment. Dive deep into the Rails codebase together, discovering why Rails behaves as it does– and how to make it behave the way you want it to.
This book will help you
Increase your productivity as a web developer
Realize the overall joy of programming with Ruby on Rails
Learn what’s new in Rails 2.0
Drive design and protect long-term maintainability with TestUnit and RSpec
Understand and manage complex program flow in Rails controllers
Leverage Rails’ support for designing REST-compliant APIs
Master sophisticated Rails routing concepts and techniques
Examine and troubleshoot Rails routing
Make the most of ActiveRecord object-relational mapping
Utilize Ajax within your Rails applications
Incorporate logins and authentication into your application
Extend Rails with the best third-party plug-ins and write your own
Integrate email services into your applications with ActionMailer
Choose the right Rails production configurations
Streamline deployment with Capistrano
Chapter 1: Rails Environment and Configurations 1
Startup 2
Default Environment Settings 2
Bootstrapping 3
RubyGems 5
Initializer 6
Default Load Paths 6
Rails, Modules, and Auto-Loading Code 7
Builtin Rails Info 8
Configuration 9
Additional Configuration 13
Development Mode 14
Automatic Class Reloading 15
The Rails Class Loader 15
Test Mode 17
Production Mode 17
Logging 18
Rails Log Files 20
Log File Analysis 22
Syslog 24
Conclusion 25
References 25
Chapter 2 Working with Controllers 27
The Dispatcher: Where It All Begins 28
Request Handling 28
Getting Intimate with the Dispatcher 29
Render unto View… 31
When in Doubt, Render 32
Explicit Rendering 33
Rendering Another Action’s Template 33
Rendering a Different Template Altogether 34
Rendering a Partial Template 35
Rendering Inline Template Code 35
Rendering Text 35
Rendering Other Types of Structured Data 36
Rendering Nothing 36
Rendering Options 37
Redirecting 39
Controller/View Communication 42
Filters 43
Filter Inheritance 44
Filter Types 46
Filter Chain Ordering 47
Around Filters 48
Filter Chain Skipping 49
Filter Conditions 50
Filter Chain Halting 50
Streaming 51
send_data(data, options = {}) 51
send_file(path, options = {}) 52
Letting the Web Server Send Files 55
Conclusion 56
References 56
Chapter 3 Routing 57
The Two Purposes of Routing 58
Bound Parameters 60
Wildcard Components (“Receptors”) 61
Static Strings 62
The routes.rb File 63
The Default Route 65
Spotlight on the :id Field 66
Default Route Generation 67
Modifying the Default Route 68
The Ante-Default Route and respond_to 69
respond_to and the HTTP-Accept Header 70
The Empty Route 71
Writing Custom Routes 72
Using Static Strings 72
Using Your Own “Receptors” 73
A Note on Route Order 75
Using Regular Expressions in Routes 76
Default Parameters and the url_for Method 76
What Happened to :id? 77
Using Literal URLs 79
Route Globbing 79
Globbing Key-Value Pairs 80
Named Routes 81
Creating a Named Route 81
The Question of Using name_path Versus name_url 82
Considerations 83
What to Name Your Routes 83
Argument Sugar 84
A Little More Sugar with Your Sugar? 85
The Special Scope Method with_options 86
Conclusion 88
References 88
Chapter 4 REST, Resources, and Rails 89
REST in a Rather Small Nutshell 89
REST in Rails 91
Routing and CRUD 92
Resources and Representations 93
REST Resources and Rails 93
From Named Routes to REST Support 94
Reenter the HTTP Verb 96
The Standard RESTful Controller Actions 96
The PUT and DELETE Cheat 98
Singular and Plural RESTful Routes 98
The Special Pairs: new/create and edit/update 99
Singular Resource Routes 100
Nested Resources 101
Setting :path_prefix Explicitly 103
Setting :name_prefix Explicitly 103
Specifying RESTful Controllers Explicitly 105
All Together Now 105
Considerations 107
Deep Nesting? 108
RESTful Route Customizations 110
Extra Member Routes 110
Extra Collection Routes 111
Considerations 112
Controller-Only Resources 113
Different Representations of Resources 115
The respond_to Method 116
Formatted Named Routes 117
The RESTful Rails Action Set 117
Index 118
Show 121
Destroy 121
New and Create 123
Edit and Update 124
Conclusion 125
Reference 126
Chapter 5 Reflecting on Rails Routing 127
Examining Routes in the Application Console 127
Dumping Routes 128
Anatomy of a Route Object 129
Recognition and Generation in the Console 132
Named Routes in the Console 134
Testing Routes 135
The Routing Navigator Plugin 136
Conclusion 137
References 137
Chapter 6 Working with ActiveRecord 139
The Basics 140
Migrations 142
Creating Migrations 143
Naming Migrations 144
Migration Pitfalls 145
Migration API 146
Defining Columns 149
Macro-Style Methods 155
Relationship Declarations 155
Convention over Configuration 156
Pluralization 157
Setting Names Manually 158
Legacy Naming Schemes 159
Defining Attributes 160
Default Attribute Values 160
Serialized Attributes 162
CRUD: Creating, Reading, Updating, Deleting 163
Creating New ActiveRecord Instances 163
Reading ActiveRecord Objects 164
Reading and Writing Attributes 166
Accessing and Manipulating Attributes Before They Are Typecast 168
Reloading 169
Dynamic Attribute-Based Finders 169
Custom SQL Queries 171
The Query Cache 172
Updating 174
Updating by Condition 176
Updating a Particular Instance 176
Updating Specific Attributes 177
Convenience Updaters 177
Controlling Access to Attributes 178
Deleting and Destroying 178
Database Locking 179
Optimistic Locking 180
Pessimistic Locking 182
Considerations 183
Advanced Finding 183
Conditions 183
Ordering of Find Results 186
Limit and Offset 186
Select Option 187
From Option 188
Group By Option 188
Locking Option 189
Joining and Including Associations 189
Read Only 189
Connections to Multiple Databases in Different Models 189
Using the Database Connection Directly 191
The DatabaseStatements Module 191
Other Connection Methods 194
Other Configuration Options 196
Conclusion 197
References 198
Chapter 7 ActiveRecord Associations 199
The Association Hierarchy 199
One-to-Many Relationships 201
Adding Associated Objects to a Collection 203
AssociationCollection Methods 204
The belongs_to Association 207
Reloading the Association 208
Building and Creating Related Objects via the Association 208
belongs_to Options 209
The has_many Association 215
has_many Options 216
Proxy Methods 224
Many-to-Many Relationships 225
has_and_belongs_to_many 225
has_many :through 233
has_many :through Options 238
:source 238
One-to-One Relationships 241
has_one 241
has_one Options 244
:Unsaved Objects and Associations 246
One-to-One Associations 246
Collections 247
Association Extensions 247
The AssociationProxy Class 249
reload and reset 249
proxy_owner, proxy_reflection, and proxy_target 249
Conclusion 250
References 251
Chapter 8 ActiveRecord Validations 253
Finding Errors 253
The Simple Declarative Validations 254
validates_acceptance_of 254
validates_associated 255
validates_confirmation_of 256
validates_each 256
validates_inclusion_of and validates_exclusion_of 257
validates_existence_of 257
validates_format_of 258
validates_length_of 259
validates_numericality_of 260
validates_presence_of 261
validates_uniqueness_of 261
RecordInvalid 263
Common Validation Options 263
:allow_nil 263
:if 263
:message 263
:on 264
Conditional Validation 264
Usage and Considerations 265
Working with the Errors Object 266
Manipulating the Errors Collection 267
Checking for Errors 267
Custom Validation 268
Skipping Validations 269
Conclusion 270
Reference 270
Chapter 9 Advanced ActiveRecord 271
Callbacks 271
Callback Registration 272
Matched before/after Callbacks 274
Halting Execution 274
Callback Usages 275
Special Callbacks: after_initialize and after_find 278
Callback Classes 279
Observers 282
Naming Conventions 283
Registration of Observers 283
Timing 284
Single-Table Inheritance (STI) 284
Mapping Inheritance to the Database 286
STI Considerations 288
STI and Associations 288
Abstract Base Model Classes 291
Polymorphic has_many Relationships 292
In the Case of Models with Comments 293
Considerations about has_many 296
Modules for Reusing Common Behavior 296
A Review of Class Scope and Contexts 299
The included Callback 300
Modifying ActiveRecord Classes at Runtime 301
Considerations 303
Ruby and Domain-Specific Languages 303
Conclusion 305
References 305
Chapter 10 ActionView 307
ERb Basics 308
ERb Practice 308
Tightening Up ERb Output 310
Commenting Out ERb Delimiters 310
Conditional Output 311
RHTML? RXML? RJS? 311
Layouts and Templates 312
Yielding Content 313
Template Variables 315
Protecting the Integrity of Your View from User-Submitted Content 319
Partials 320
Simple Use Cases 321
Reuse of Partials 322
Shared Partials 323
Passing Variables to Partials 324
Render Collections 325
Logging 327
Caching 327
Caching in Development Mode? 328
Page Caching 328
Action Caching 328
Fragment Caching 330
Expiration of Cached Content 333
Automatic Cache Expiry with Sweepers 335
Cache Logging 337
Action Cache Plugin 337
Cache Storage 338
Conclusion 340
References 340
Chapter 11 All About Helpers 341
ActiveRecordHelper 342
Reporting Validation Errors 342
Automatic Form Creation 344
Customizing the Way Validation Errors Are Highlighted 346
AssetTagHelper 348
Head Helpers 348
For Plugins Only, Add Default JavaScript Includes 352
BenchmarkHelper 353
benchmark(message = “Benchmarking”, level = :info) 353
CacheHelper 353
CaptureHelper 354
capture(&block) 354
content_for(name, &block) 354
DateHelper 355
The Date and Time Selection Helpers 355
The Individual Date and Time Select Helpers 356
Common Options for Date Selection Helpers 359
distance_in_time Methods with Complex Descriptive Names 359
DebugHelper 361
FormHelper 362
Creating Forms for ActiveRecord Models 362
How Form Helpers Get Their Values 370
FormOptionsHelper 371
Select Helpers 371
Option Helpers 373
FormTagHelper 378
check_box_tag(name, value = “1”, checked = false, options = {}) 378
end_form_tag 378
file_field_tag(name, options = {}) 378
form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block) 379
hidden_field_tag(name, value = nil, options = {}) 380
image_submit_tag(source, options = {}) 380
password_field_tag(name = “password”, value = nil, options = {}) 380
radio_button_tag(name, value, checked = false, options = {}) 380
select_tag(name, option_tags = nil, options = {}) 380
start_form_tag 380
submit_tag(value = “Save changes”, options = {}) 381
text_area_tag(name, content = nil, options = {}) 381
text_field_tag(name, value = nil, options = {}) 381
JavaScriptHelper 381
button_to_function(name, function, html_options={}, &block) 381
define_javascript_functions() 382
escape_javascript(javascript) 382
javascript_tag(content, html_options={}) 382
link_to_function(name, function, html_options={}, &block) 382
NumberHelper 383
human_size(size, precision=1) 383
number_to_currency(number, options = {}) 383
number_to_human_size(size, precision=1) 384
number_to_percentage(number, options = {}) 384
number_to_phone(number, options = {}) 385
number_with_delimiter(number, delimiter=”,”, separator=”.”) 385
number_with_precision(number, precision=3) 385
PaginationHelper 386
will_paginate 386
paginator 387
Paginating Find 388
RecordIdentificationHelper 388
dom_class(record_or_class, prefix = nil) 389
dom_id(record, prefix = nil) 389
partial_path(record_or_class) 389
RecordTagHelper 390
content_tag_for(tag_name, record, *args, &block) 390
div_for(record, *args, &block) 391
TagHelper 391
cdata_section(content) 391
content_tag(name, content = nil, options = nil, &block) 391
escape_once(html) 392
tag(name, options = nil, open = false) 392
TextHelper 393
auto_link(text, link = :all, href_options = {}, &block) 393
concat(string, binding) 393
cycle(first_value, *values) 394
excerpt(text, phrase, radius = 100, excerpt_string = “...”) 395
highlight(text, phrases, highlighter = ‘<strong rdquo;highlight”>\1</strong>’) 395
markdown(text) 396
pluralize(count, singular, plural = nil) 396
reset_cycle(name = “default”) 397
sanitize(html) 397
simple_format(text) 398
strip_links(text) 398
strip_tags(html) 398
textilize(text) 399
textilize_without_paragraph(text) 399
truncate(text, length = 30, truncate_string = “...”) 399
word_wrap(text, line_width = 80) 400
UrlHelper 400
button_to(name, options = {}, html_options = {}) 400
current_page?(options) 401
link_to(name, options = {}, html_options = nil) 401
link_to_if(condition, name, options = {}, html_options = {}, &block) 403
link_to_unless(condition, name, options = {}, html_options = {}, &block) 403
link_to_unless_current(name, options = {}, html_options = {}, &block) 403
mail_to(email_address, name = nil, html_options = {}) 404
url_for(options = {}) 405
Relying on Named Routes 406
Writing Your Own Helpers 407
Small Optimizations: The Title Helper 407
Encapsulating View Logic: The photo_for Helper 408
Smart View: The breadcrumbs Helper 409
Wrapping and Generalizing Partials 410
A tiles Helper 410
Generalizing Partials 414
Conclusion 417
References 417
Chapter 12 Ajax on Rails 419
Prototype 420
FireBug 421
The Prototype API 421
Top-Level Functions 422
Class 424
Extensions to JavaScript’s Object Class 425
Extensions to JavaScript’s Array Class 426
Extensions to the document Object 428
Extensions to the Event Class 428
Extensions to JavaScript’s Function Class 430
Extensions to JavaScript’s Number Class 432
Extensions to JavaScript’s String class 433
string.dasherize() 434
string.escapeHTML() and string.unescapeHTML() 434
string.evalScripts() and string.extractScripts() 434
string.gsub(pattern, replacement) and string.sub(pattern, replacement, count) 434
string.scan(pattern, iterator) 434
string.strip() 435
string.stripScripts() and string.stripTags() 435
string.parseQuery() and string.toQueryParams() 435
string.toArray() 435
string.truncate(length, truncationString) 435
string.underscore() 436
The Ajax Object 436
Ajax.Responders 437
Enumerable 437
Hash 443
ObjectRange 444
The Prototype Object 445
The PrototypeHelper Module 445
link_to_remote 445
remote_form_for 449
periodically_call_remote 451
observe_field 451
observe_form 453
RJS–Writing Javascript in Ruby 453
RJS Templates 455
<<(javascript) 456
[](id) 457
alert(message) 457
call(function, *arguments, &block) 457
delay(seconds = 1) { ... } 458
draggable(id, options = {}) 458
drop_receiving(id, options = {}) 458
hide(*ids) 458
insert_html(position, id, *options_for_render) 458
literal(code) 459
redirect_to(location) 459
remove(*ids) 459
replace(id, *options_for_render) 460
replace_html(id, *options_for_render) 460
select(pattern) 460
show(*ids) 460
sortable(id, options = {}) 460
toggle(*ids) 461
visual_effect(name, id = nil, options = {}) 461
JSON 461
Drag and Drop 463
00_5619_fm.qxd 10/25/07 4:05 PM Page xxxii
Sortable 465
Autocompleter 466
In-Place Editors 467
Conclusion 467
References 468
Chapter 13 Session Management 469
What to Store in the Session 470
The Current User 470
Session Use Guidelines 470
Session Options 471
Disabling Sessions for Robots 472
Selectively Enabling Sessions 473
Secure Sessions 473
Storage Mechanisms 473
ActiveRecord SessionStore 473
PStore (File-Based) 474
DRb Session Storage 475
memcache Session Storage 475
The Controversial CookieStore 476
Timing Out and Session Life Cycle 478
Session Timeout Plugin for Rails 478
Tracking Active Sessions 479
Enhanced Session Security 480
Cleaning Up Old Sessions 481
Cookies 481
Reading and Writing Cookies 482
Conclusion 483
References 483
Chapter 14 Login and Authentication 485
Acts as Authenticated 486
Installation and Setup 486
The User Model 487
The Account Controller 496
Login from Cookie 498
The Current User 499
Logging In During Testing 501
Conclusion 502
References 502
Chapter 15 XML and ActiveResource 503
The to_xml Method 503
Customizing to_xml Output 505
Associations and to_xml 507
Advanced to_xml 508
Dynamic Runtime Attributes 509
Overriding to_xml 510
Learning from Array’s to_xml Method 510
The XML Builder 513
Parsing XML 515
Turning XML into Hashes 515
XmlSimple 516
Typecasting 518
ActiveResource 519
Find 519
Create 522
Update 524
Delete 524
Headers 526
Customizing 527
Hash Forms 528
Conclusion 529
Chapter 16 ActionMailer 531
Setup 531
Mailer Models 532
Preparing Outbound Email Messages 533
HTML Email Messages 536
Multipart Messages 537
File Attachments 539
Actually Sending an Email 540
Receiving E-Mails 540
TMail::Mail API Reference 541
Handling Attachments 543
Configuration 543
Conclusion 544
References 544
Chapter 17 Testing 545
Rails Testing Terminology 546
So Much for Isolation... 547
Rails Mocks? 548
Real Mocks and Stubs 549
Integration Tests 550
Dealing with the Confusion 551
Test::Unit 552
Running Tests 553
Fixtures 554
CSV Fixtures 555
Accessing Fixture Records from Tests 556
Dynamic Fixture Data 556
Using Fixture Data in Development Mode 557
Generating Fixtures from Development Data 558
Fixtures Options 559
Everybody Hates Fixtures 560
Fixtures Really Aren’t That Bad 562
Assertions 562
Basic Assertions 562
Rails Assertions 566
One Assertion per Test Method 566
Testing Models with Unit Tests 568
Model Testing Basics 568
Deciding What to Test 570
Testing Controllers with Functional Tests 570
Structure and Setup 570
Functional Test Methods 571
Common Assertions 572
Testing Views with Functional Tests 576
assert_select(selector, [*values, equality, message, &block]) 577
assert_select(element, selector, [*values, equality, message, &block]) 577
Optional Block Parameter 577
Selector Reference 578
Equality Tests 580
Testing RJS Behavior 581
Other Selection Methods 582
Testing Routing Rules 582
Rails Integration Tests 584
Basics 584
The Integration Test API 585
Working with Sessions 586
Rake Tasks Related to Testing 587
Acceptance Tests 588
Acceptance Test First? 588
Selenium 589
Basics 589
Getting Started 591
RSelenese 592
Conclusion 593
References 594
Chapter 18 RSpec on Rails 597
Introduction to RSpec 597
Should and Expectations 598
Predicates 599
Custom Expectation Matchers 601
Multiple Examples per Behavior 603
Shared Behaviors 604
RSpec’s Mocks and Stubs 607
Running Specs 610
Installing RSpec and the RSpec on Rails Plugin 613
The RSpec on Rails Plugin 613
Generators 614
Model Specs 614
Controller Specs 617
View Specs 621
Helper Specs 623
Scaffolding 623
RSpec Tools 624
Autotest 624
RCov 624
Conclusion 625
References 626
Chapter 19 Extending Rails with Plugins 627
Managing Plugins 628
Reusing Code 628
T he Plugin Script 629
Subversion and script/plugin 633
Using Piston 636
Installation 636
Importing a Vendor Library 637
Converting Existing Vendor Libraries 638
Updating 638
Locking and Unlocking Revisions 639
Piston Properties 639
Writing Your Own Plugins 640
The init.rb Hook 640
The lib Directory 642
Extending Rails Classes 643
The README and MIT-LICENSE File 644
The install.rb and uninstall.rb Files 645
Custom Rake Tasks 647
The Plugin’s Rakefile 648
Testing Plugins 649
Conclusion 649
References 650
Chapter 20 Rails Production Configurations 651
A Brief History of Rails In Production 652
Some Basic Prerequisites 652
The Stack Checklist 654
Server and Network Environment 655
Web Tier 656
Application Tier 656
Database Tier 656
Monitoring 657
Version Control 657
Installations 657
Ruby 658
RubyGems 658
Rails 659
Mongrel 659
Mongrel Cluster 659
Nginx 659
Subversion 660
MySQL 660
Monit 661
Capistrano 661
Configurations 661
Configuring Mongrel Cluster 662
Configuring Nginx 663
Configuring Monit 667
Configuring Capistrano 670
Configuring init Scripts 670
Nginx init Script 670
Mongrel init Script 672
Monit Configuration 673
Deployment and Launch 675
Other Production Stack Considerations 675
Redundancy and Failover 676
Caching 676
Performance and Scalability 676
Security 677
Maintainability 678
Conclusion 678
References 679
Chapter 21 Capistrano 681
Overview of Capistrano 681
Terminology 682
The Basics 682
What Do I Need to Do to Use Capistrano? 682
What Does Capistrano Expect? 683
What Has Capistrano Done and What Hasn’t It? 684
Getting Started 684
Installation 684
“Capify” Your Rails Application 685
Configuring the Deployment 687
A Little Spin, Please… 688
Set Up the Deployment Machine 689
Deploy! 691
Overriding Capistrano Assumptions 691
Using a Remote User Account 691
Customizing the SCM System Used by Capistrano 692
Working without SCM Access from the Deployment Machine 692
What If I Don’t Store database.yml in My SCM Repository? 693
What If My Migrations Won’t Run from 0 to 100? 696
Useful Capistrano Recipes 696
Variables and Their Scope 696
Exercise #1: Staging 698
Exercise #2: Managing Other Services 701
Multiserver Deployments 702
Transactions 703
Proxied Access to Deployment Machines 705
Conclusion 706
References 706
Chapter 22 Background Processing 707
script/runner 708
Getting Started 708
Usage Notes 709
script/runner Considerations 710
DRb 710
A Simple DRb Server 711
Using DRb from Rails 711
DRb Considerations 712
Resources 713
BackgrounDRb 713
Getting Started 713
Configuration 714
Understanding BackgrounDRb 715
Using the MiddleMan 715
Caveats 717
BackGrounDRb Considerations 718
Daemons 719
Usage 719
Introducing Threads 720
Daemon Considerations 722
Conclusion 722
References 722
Appendix A ActiveSupport API Reference 723
Appendix B Rails Essentials 805
Afterword What Is the Rails Way (To You)? 815