Preface |
|
xv | |
Acknowledgments |
|
xvii | |
About this book |
|
xx | |
1 Ruby on Rails, the framework |
|
1 | (24) |
|
1.1 Ruby on Rails overview |
|
|
2 | (4) |
|
|
2 | (1) |
|
|
3 | (1) |
|
|
4 | (1) |
|
|
5 | (1) |
|
1.2 Developing your first application |
|
|
6 | (17) |
|
|
6 | (1) |
|
Generating an application |
|
|
6 | (1) |
|
|
7 | (1) |
|
|
8 | (1) |
|
|
9 | (2) |
|
Viewing and creating purchases |
|
|
11 | (3) |
|
|
14 | (3) |
|
|
17 | (1) |
|
|
18 | (3) |
|
|
21 | (2) |
|
|
23 | (2) |
2 Testing saves your bacon |
|
25 | (14) |
|
2.1 Using TDD and BDD to save your bacon |
|
|
26 | (1) |
|
2.2 Test-driven development basics |
|
|
27 | (4) |
|
|
27 | (2) |
|
|
29 | (2) |
|
2.3 Behavior-driven development basics |
|
|
31 | (7) |
|
|
31 | (1) |
|
|
32 | (1) |
|
|
33 | (1) |
|
|
34 | (1) |
|
|
35 | (3) |
|
|
38 | (1) |
3 Developing a real Rails application |
|
39 | (45) |
|
|
41 | (1) |
|
|
41 | (1) |
|
|
41 | (1) |
|
|
42 | (4) |
|
Getting started with GitHub |
|
|
43 | (1) |
|
Configuring your Git client |
|
|
44 | (2) |
|
3.3 Application configuration |
|
|
46 | (5) |
|
The Gemfile and generators |
|
|
47 | (3) |
|
|
50 | (1) |
|
3.4 Beginning your first feature |
|
|
51 | (32) |
|
|
52 | (3) |
|
Defining a controller action |
|
|
55 | (2) |
|
|
57 | (17) |
|
|
74 | (1) |
|
|
74 | (3) |
|
|
77 | (6) |
|
|
83 | (1) |
4 Oh, CRUD! |
|
84 | (40) |
|
|
85 | (3) |
|
|
85 | (2) |
|
Adding a link to a project |
|
|
87 | (1) |
|
|
88 | (6) |
|
|
88 | (4) |
|
|
92 | (2) |
|
|
94 | (3) |
|
4.4 What happens when things can't be found |
|
|
97 | (5) |
|
|
98 | (1) |
|
Handling the ActiveRecord::RecordNotFound exception |
|
|
99 | (3) |
|
4.5 Styling the application |
|
|
102 | (21) |
|
|
103 | (1) |
|
Improving the page's header |
|
|
104 | (2) |
|
|
106 | (1) |
|
|
107 | (6) |
|
|
113 | (4) |
|
|
117 | (3) |
|
|
120 | (3) |
|
|
123 | (1) |
5 Nested resources |
|
124 | (24) |
|
|
124 | (12) |
|
|
126 | (1) |
|
Creating a tickets controller |
|
|
127 | (1) |
|
Demystifying the new action |
|
|
128 | (1) |
|
Defining a has many association |
|
|
129 | (2) |
|
Creating tickets in a project |
|
|
131 | (2) |
|
Finding tickets scoped by project |
|
|
133 | (2) |
|
|
135 | (1) |
|
|
136 | (5) |
|
|
138 | (1) |
|
|
139 | (2) |
|
|
141 | (4) |
|
|
141 | (3) |
|
|
144 | (1) |
|
|
144 | (1) |
|
|
145 | (2) |
|
|
147 | (1) |
6 Authentication |
|
148 | (22) |
|
|
149 | (3) |
|
|
152 | (2) |
|
6.3 Adding sign-in and sign-out |
|
|
154 | (7) |
|
|
154 | (3) |
|
|
157 | (2) |
|
|
159 | (2) |
|
6.4 Linking tickets to users |
|
|
161 | (7) |
|
Fixing the failing four features |
|
|
167 | (1) |
|
|
168 | (2) |
7 Basic access control |
|
170 | (45) |
|
7.1 Turning users into admins |
|
|
171 | (3) |
|
Adding the admin field to the users table |
|
|
172 | (1) |
|
Creating the first admin user |
|
|
173 | (1) |
|
7.2 Controller namespacing |
|
|
174 | (13) |
|
Generating a namespaced controller |
|
|
174 | (3) |
|
Testing a namespaced controller |
|
|
177 | (3) |
|
Moving functionality into the admin namespace |
|
|
180 | (7) |
|
|
187 | (4) |
|
Hiding the "New Project" link |
|
|
187 | (2) |
|
|
189 | (2) |
|
|
191 | (23) |
|
|
193 | (2) |
|
|
195 | (1) |
|
|
196 | (1) |
|
|
197 | (2) |
|
|
199 | (4) |
|
The edit and update actions |
|
|
203 | (2) |
|
|
205 | (5) |
|
Ensuring that you can't archive yourself |
|
|
210 | (1) |
|
Preventing archived users from signing in |
|
|
211 | (3) |
|
|
214 | (1) |
8 Fine-grained access control |
|
215 | (68) |
|
8.1 Project-viewing permission |
|
|
216 | (20) |
|
|
217 | (2) |
|
|
219 | (1) |
|
|
220 | (3) |
|
Testing the ProjectPolicy |
|
|
223 | (4) |
|
|
227 | (3) |
|
Handling authorization errors |
|
|
230 | (2) |
|
|
232 | (4) |
|
8.2 Project-updating permission |
|
|
236 | (6) |
|
Testing the ProjectPolicy again |
|
|
236 | (2) |
|
Applying the authorization |
|
|
238 | (2) |
|
Hiding the "Edit Project" link |
|
|
240 | (2) |
|
8.3 Ticket-viewing permission |
|
|
242 | (8) |
|
|
243 | (3) |
|
|
246 | (3) |
|
|
249 | (1) |
|
8.4 Ticket-creation permission |
|
|
250 | (6) |
|
Testing the TicketPolicy...again |
|
|
250 | (2) |
|
Applying the authorization |
|
|
252 | (4) |
|
8.5 Ticket-updating permission |
|
|
256 | (6) |
|
Testing the TicketPolicy...turbocharged |
|
|
256 | (2) |
|
Implementing controller authorization |
|
|
258 | (1) |
|
Hiding the "Edit Ticket" link |
|
|
259 | (3) |
|
8.6 Ticket-destroying permission |
|
|
262 | (4) |
|
Testing the TicketPolicy...for the final time |
|
|
262 | (2) |
|
Implementing controller authorization |
|
|
264 | (2) |
|
8.7 Ensuring authorization for all actions |
|
|
266 | (3) |
|
8.8 Assigning roles to users |
|
|
269 | (13) |
|
Planning the permission screen with a feature spec |
|
|
270 | (1) |
|
|
271 | (1) |
|
Building a list of projects in a select box |
|
|
271 | (7) |
|
Processing the submitted role data |
|
|
278 | (2) |
|
Saving roles of new users |
|
|
280 | (2) |
|
|
282 | (1) |
9 File uploading |
|
283 | (42) |
|
|
284 | (9) |
|
A feature featuring files |
|
|
285 | (1) |
|
Enter, stage right: CarrierWave |
|
|
286 | (1) |
|
|
287 | (3) |
|
Persisting uploads when redisplaying a form |
|
|
290 | (3) |
|
|
293 | (9) |
|
Testing multiple-file upload |
|
|
293 | (1) |
|
Implementing multiple-file upload |
|
|
294 | (4) |
|
|
298 | (4) |
|
9.3 Serving files through a controller |
|
|
302 | (8) |
|
Testing existing functionality |
|
|
303 | (1) |
|
|
304 | (2) |
|
|
306 | (1) |
|
|
307 | (1) |
|
|
308 | (2) |
|
|
310 | (7) |
|
|
310 | (2) |
|
|
312 | (2) |
|
|
314 | (2) |
|
Adding more files with JavaScript |
|
|
316 | (1) |
|
9.5 Responding to an asynchronous request |
|
|
317 | (7) |
|
Appending new content to the form |
|
|
320 | (2) |
|
Sending parameters for an asynchronous request |
|
|
322 | (2) |
|
|
324 | (1) |
10 Tracking state |
|
325 | (57) |
|
|
326 | (16) |
|
|
328 | (4) |
|
|
332 | (10) |
|
10.2 Changing a ticket's state |
|
|
342 | (11) |
|
|
343 | (2) |
|
|
345 | (7) |
|
Setting a default state for a comment |
|
|
352 | (1) |
|
Seeding your app with states |
|
|
352 | (1) |
|
|
353 | (8) |
|
|
353 | (2) |
|
|
355 | (1) |
|
|
356 | (2) |
|
|
358 | (3) |
|
|
361 | (12) |
|
|
361 | (6) |
|
|
367 | (4) |
|
Applying the default state |
|
|
371 | (2) |
|
Setting a default state in seed states |
|
|
373 | (1) |
|
|
373 | (8) |
|
|
373 | (2) |
|
Defining the change state permission |
|
|
375 | (1) |
|
|
376 | (2) |
|
|
378 | (3) |
|
|
381 | (1) |
11 Tagging |
|
382 | (38) |
|
|
384 | (7) |
|
|
384 | (2) |
|
|
386 | (1) |
|
Defining the tags association |
|
|
387 | (1) |
|
|
387 | (1) |
|
Displaying a ticket's tags |
|
|
388 | (3) |
|
|
391 | (5) |
|
Adding tags through a comment |
|
|
392 | (4) |
|
|
396 | (6) |
|
|
396 | (5) |
|
Tags are allowed, for some |
|
|
401 | (1) |
|
|
402 | (7) |
|
|
403 | (1) |
|
Adding a link to delete the tag |
|
|
404 | (4) |
|
Removing a tag from the page |
|
|
408 | (1) |
|
|
409 | (10) |
|
|
409 | (3) |
|
|
412 | (4) |
|
|
416 | (1) |
|
Search, but without the search |
|
|
417 | (2) |
|
|
419 | (1) |
12 Sending email |
|
420 | (28) |
|
12.1 Sending ticket notifications |
|
|
421 | (16) |
|
Automatically watching a ticket |
|
|
421 | (2) |
|
|
423 | (4) |
|
Defining the watchers association |
|
|
427 | (2) |
|
Introducing Action Mailer |
|
|
429 | (3) |
|
An Action Mailer template |
|
|
432 | (2) |
|
Testing with mailer specs |
|
|
434 | (3) |
|
12.2 Subscribing to updates |
|
|
437 | (9) |
|
Testing comment subscription |
|
|
437 | (2) |
|
Automatically adding the commenter to the watchers list |
|
|
439 | (1) |
|
Unsubscribing from ticket notifications |
|
|
440 | (6) |
|
|
446 | (2) |
13 Deployment |
|
448 | (20) |
|
|
449 | (1) |
|
13.2 Simple deployment with Heroku |
|
|
450 | (2) |
|
|
450 | (1) |
|
|
450 | (2) |
|
|
452 | (5) |
|
|
452 | (1) |
|
|
453 | (1) |
|
|
454 | (3) |
|
|
457 | (5) |
|
|
458 | (2) |
|
Fixing CarrierWave file uploads |
|
|
460 | (2) |
|
|
462 | (1) |
|
13.5 Continuous deployment with Travis CI |
|
|
462 | (3) |
|
|
462 | (1) |
|
|
463 | (2) |
|
|
465 | (2) |
|
|
467 | (1) |
14 Designing an API |
|
468 | (28) |
|
|
469 | (2) |
|
|
470 | (1) |
|
14.2 Using ActiveModel::Serializers |
|
|
471 | (5) |
|
|
473 | (3) |
|
14.3 API authentication and authorization |
|
|
476 | (10) |
|
|
477 | (4) |
|
A small tangent on inflections |
|
|
481 | (2) |
|
|
483 | (3) |
|
14.4 It's not a party without...HTTParty |
|
|
486 | (1) |
|
|
487 | (7) |
|
Authenticating with a blank token |
|
|
488 | (1) |
|
|
489 | (2) |
|
|
491 | (3) |
|
|
494 | (1) |
|
|
495 | (1) |
15 Rack-based applications |
|
496 | (27) |
|
15.1 Building Rack applications |
|
|
497 | (5) |
|
|
498 | (1) |
|
Let's increase the heartbeat |
|
|
499 | (2) |
|
|
501 | (1) |
|
15.2 Building bigger Rack applications |
|
|
502 | (4) |
|
|
503 | (2) |
|
Running a combined Rack application |
|
|
505 | (1) |
|
15.3 Mounting a Rack application with Rails |
|
|
506 | (11) |
|
|
507 | (1) |
|
|
508 | (1) |
|
|
509 | (6) |
|
|
515 | (2) |
|
|
517 | (4) |
|
|
518 | (1) |
|
|
519 | (1) |
|
|
520 | (1) |
|
|
521 | (2) |
Appendix A Installation Guide |
|
523 | (12) |
Appendix B Why Rails? |
|
535 | (6) |
Index |
|
541 | |