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