1. Trang chủ
  2. » Công Nghệ Thông Tin

rails 3 in action

592 2K 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Rails 3 in Action
Tác giả Ryan Bigg, Yehuda Katz
Trường học Shelter Island
Chuyên ngành Software Development
Thể loại Book
Năm xuất bản 2012
Thành phố Shelter Island
Định dạng
Số trang 592
Dung lượng 8,14 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

I’d like to think that it offers a unique perspective on developing a full Ruby on Rails tion from scratch in the same or at least, similar manner that people are developingRails applica

Trang 1

Ryan Bigg

Yehuda Katz

IN ACTION

Trang 2

Rails 3 in Action

Trang 4

Rails 3 in Action

RYAN BIGG YEHUDA KATZ

M A N N I N G

SHELTER ISLAND

Trang 5

For online information and ordering of this and other Manning books, please visit

www.manning.com The publisher offers discounts on this book when ordered in quantity For more information, please contact

Special Sales Department

Manning Publications Co

20 Baldwin Road

PO Box 261

Shelter Island, NY 11964

Email: orders@manning.com

©2012 by Manning Publications Co All rights reserved

No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher

Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks Where those designations appear in the book, and Manning

Publications was aware of a trademark claim, the designations have been printed in initial caps

or all caps

Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end Recognizing also our responsibility to conserve the resources of our planet, Manning booksare printed on paper that is at least 15 percent recycled and processed without the use of elemental chlorine

Manning Publications Co Development editor: Cynthia Kane

20 Baldwin Road Copyeditors: Kevin Hobson, Linda Kern

PO Box 261 Proofreader: Tiffany Taylor

Shelter Island, NY 11964 Typesetter: Dottie Marsico

Cover designer: Marija Tudor

ISBN 978-1-935182-27-6

Printed in the United States of America

1 2 3 4 5 6 7 8 9 10 – MAL – 16 15 14 13 12 11

Trang 6

brief contents

1 ■ Ruby on Rails, the framework 1

2 ■ Testing saves your bacon 23

3 ■ Developing a real Rails application 44

5 ■ Nested resources 99

6 ■ Authentication and basic authorization 117

7 ■ Basic access control 136

Trang 8

contents

preface xv

acknowledgments xvii

about this book xx

about the authors xxiii

about the cover illustration xxiv

1 Ruby on Rails, the framework 1

1.1 What is Ruby on Rails? 2

Benefits 2Common terms 3Rails in the wild 4

1.2 Developing your first application 5

Installing Rails 5Generating an application 6Starting the application 6Scaffolding 7Migrations 8Viewing and creating purchases 9Validations 13Showing off 14 Routing 15Updating 16Deleting 20

2 Testing saves your bacon 23

2.1 Test- and behavior-driven development 24

Trang 9

3 Developing a real Rails application 44

3.1 Application setup 45

The application story 45Version control 47The Gemfile and generators 50Database configuration 53Applying a stylesheet 54

6 Authentication and basic authorization 117

6.1 What Devise does 118

Installing Devise 118

Trang 10

CONTENTS ix

6.2 User signup 121

6.3 Confirmation link sign-in 122

Testing email 122Confirming confirmation 123

6.4 Form sign-in 126

6.5 Linking tickets to users 128

Attributing tickets to users 129We broke something! 131 Fixing the Viewing Tickets feature 132Fixing the Editing Tickets feature 133Fixing the Deleting Tickets feature 134

7 Basic access control 136

7.1 Projects can be created only by admins 137

7.2 Adding the admin field to the users table 138

7.3 Restricting actions to admins only 138

Fixing three more broken scenarios 143Hiding the New Project link 144Hiding the edit and delete links 146

8.3 Fixing what you broke 172

Fixing Editing Projects 173Fixing the four failing features 173One more thing 176Fixing Signing Up 178

8.4 Blocking access to tickets 183

Locking out the bad guys 183

Trang 11

8.5 Restricting write access 185

Rewriting a feature 185Blocking creation 187What is CanCan? 188Adding abilities 189

8.6 Restricting update access 190

No updating for you! 191Authorizing editing 192

8.7 Restricting delete access 193

Enforcing destroy protection 193Hiding links based on permission 194

9.2 Attaching many files 220

Two more files 221Using nested attributes 224

9.3 Serving files through a controller 226

Protecting files 227Showing your assets 228Public assets 230Privatizing assets 230

9.4 Using JavaScript 231

JavaScript testing 232Introducing jQuery 233Adding more files with JavaScript 234Responding to an asynchronous request 235Sending parameters for an asynchronous

10.2 Changing a ticket’s state 252

Creating the State model 253Selecting states 255 Callbacks 257Seeding states 259Fixing creating comments 261

Trang 12

CONTENTS xi

10.3 Tracking changes 263

Ch-ch-changes 263Another c-c-callback 264Displaying changes 265Show me the page 266Automatic escaping saves your bacon 267Styling states 268

10.4 Managing states 269

Adding additional states 270Defining a default state 273

10.5 Locking down states 278

Hiding a select box 278Bestowing changing state permissions 280Hacking a form 282Ignoring a parameter 283

11.2 Adding more tags 292

Adding tags through a comment 292Fixing the CommentsController spec 294

12.1 Sending ticket notifications 313

Automatically watching a ticket 314Using observers 315 Defining the watchers association 316Introducing Action Mailer 318An Action Mailer template 320Delivering HTML emails 322

Trang 13

12.2 Subscribing to updates 325

Testing comment subscription 325Automatically adding a user

to a watchlist 327Unsubscribing from ticket notifications 328

13.1 The projects API 349

Your first API 351Serving an API 354API authentication 355Error reporting 356Serving XML 358Creating projects 360Restricting access to only admins 362A single project 365No project for you! 368 Updating a project 370Exterminate! 372

13.2 Beginning the tickets API 374 13.3 Rate limiting 377

One request, two request, three request, four 377No more, thanks! 379Back to zero 380

Installing RVM 389Installing Ruby 390

14.3 Creating a user for the app 391

Key-based authentication 391Disabling password authentication 393

14.4 The database server 394

Creating a database and user 394Ident authentication 395

Trang 14

CONTENTS xiii

14.5 Deploy away! 395

Deploy keys 396Configuring Capistrano 397Setting up the deploy environment 400Deploying the application 401 Bundling gems 403Choosing a database 405

16.2 Database query enhancements 444

Eager loading 445Database indexes 446

16.3 Page and action caching 448

Caching a page 448Caching an action 451Cache sweepers 454Client-side caching 457Caching page fragments 460

16.4 Background workers 462

17.1 A brief history of engines 469

17.2 Why engines are useful 470

17.3 Brand-new engine 471

Creating an engine 471The layout of an engine 472 Engine routing 476

Trang 15

17.4 Setting up a testing environment 478

Removing Test::Unit 479Installing RSpec and Capybara 481

17.5 Writing your first engine feature 482

Your first Capybara test 483Setting up routes 484The topics controller 485The index action 485The new action 488The create action 489The show action 490 Showing an association count 492

17.6 Adding more posts to topics 493 17.7 Classes outside your control 497

Engine configuration 497A fake User model 500 Authenticating topics 501Adding authorship to topics 505 Post authentication 506Showing the last post 509

17.8 Releasing as a gem 512 17.9 Integrating with an application 513

18 Rack-based applications 516

18.1 Building Rack applications 517

A basic Rack application 518

18.2 Building bigger Rack applications 522

You’re breaking up 522Running a combined Rack application 524

18.3 Mounting a Rack application with Rails 525

Mounting Heartbeat 526Introducing Sinatra 527 The API, by Sinatra 528Basic error checking 532

Trang 16

preface

This book has been through quite the development process! It began in 2008 with

Michael Ivey, Yehuda Katz, and Ezra Zygmuntowicz and was called Merb in Action Since

then it has changed name and hands a couple of times, winding up with people such asJames Cox and the great Mike Gunderloy, the latter of whom is probably most famousfor his work on Factsheet Five and many NET books, not to mention being one of thefounding members of the RailsBridge (http://railsbridge.org) organization

Then, somehow, I became involved with this book

I received an email on a cold April morning in 2010 from Christina Rudloff atManning asking if I would have any interest in joining the project I was exceptionallyexcited! I had been writing short blog posts about Rails for years, and the idea offocusing that effort into writing a book made me extremely happy Long story short:Yehuda Katz liked what he saw on my blog and wanted me to join the project Workingwith Yehuda has been brilliant He’s got to be one of the smartest and most patientpeople I have ever met

Shortly after receiving that initial email from Christina, I talked with another son from Manning, Michael Stephens, first via email and then very late at night overthe phone (we are on different continents) about the project I worked out the initialchapter layout, and I distinctly remember one thing that Michael asked me: “Youknow what you’re getting yourself into, right?” I thought “Sure, I’ve written blog postsbefore, how hard could it be?” and replied in much the same manner How little did

per-I know!

Since then, I have learned a lot about the book-writing process For starters, itinvolves a lot more than just the two people and the publishing company on the front

Trang 17

cover It also takes a very long time to write a book This book has been my life for thepast year and a bit I’ve spent many weekends, mornings before work, and eveningsafter work (and way too often, time even in my dreams) writing chapters for this book.I’ve talked about it (perhaps too much) as well It’s become such a running jokeamong people I know that when I’m introduced, they ask, “Do you know he’s writing abook?”

Writing is sometimes easy, but other times it can be a struggle to come up with thing at all There have been bad days, sure, but the good days outnumber those mas-sively The feeling of achievement you get when you finish a chapter, or even a section,

any-is awesome Receiving positive feedback from people has been a huge boon to pleting this book

Now, in 2011, the book is finally done, and what an amazing feeling that is! I’d like

to think that it offers a unique perspective on developing a full Ruby on Rails tion from scratch in the same (or at least, similar) manner that people are developingRails applications at this time It’s also the first book to cover the latest features ofRails found in version 3.1

RYAN BIGG

Trang 18

acknowledgments

This has been an amazing process, full of amazing people A large portion of thisbook would not have been possible without the support of my employer, Mikel Lind-saar, and company, RubyX, allowing me to take time off to write the book The sup-port of the community at large has also been enormous in helping me complete thisbook Winning the Ruby Hero award at RailsConf, partially due to my work on thisvery book, was the highlight of my career so far After I won the award, Mikel also pro-vided me with a new laptop at no expense to replace my previous one that was threeyears old Bloody champion!

Of course, a lot of this wouldn’t have been as easy if it wasn’t for the Rails CoreTeam’s valiant efforts on their maintenance of the framework over the years and theirconstant focus on improving people’s lives on an almost daily basis Also there areYehuda Katz, Carl Lerche, and André Arko to thank for their work on an importantpart of developing not only Rails applications, but also Ruby libraries such as Bundlerand Thor These people are my idols, and I love them dearly

Through a Rails-based review system called Twist that I built myself over a singleday, I’ve collected more than 1,200 notes from people from around the world whohave been reviewing the book as I have been writing it A special mention goes to thethree people who’ve left the most notes in Twist: Roy Hacker, Deryl Doucette, andPeter Ley An almost-as-special mention goes to the 33 other people who’ve also leftnotes Without your help, this book wouldn’t be half as brilliant as it is today

Also thanks to Tim McEwan for the ideas for the engines chapter, Chris Darrochfor an initial read-through of the first chapters, and Rob Zolkos for helping with some

Trang 19

gnarly ePub Ruby and XLST code And yes, thanks to Andrew Snow for assisting with adifficult moral problem in chapter 16 at Railscamp in June 2011.

In addition to those who’ve been leaving notes in Twist, there are the people atManning First, thanks to Christina Rudloff for the initial contact and Michael Ste-phens for the late-night chats and management of the process Candace Gillhooleyand Nick Chase have also been enormously helpful

Cynthia Kane, my development editor at Manning, is particularly special Her jobwas to tell me when I was doing things wrong, such as not segueing between sections

or making the text flow too fast, and to leave me notes such as “FIGURE!!!” when Ineeded an image to go along with the text Our almost weekly catch-ups were wellworthwhile; it was great always having someone there, prodding me for more contentand talking through the process Marjan Bace, fearless leader of Manning Publica-tions, should also be credited for supporting this project for as long as it has beenaround

The production team at Manning, including Troy Mott, has been great throughoutthis process too The extreme focus they’ve shown in finishing this book is stunning Ialso need to mention the wonderful work by Doug Warren in the final technicalproofing of the book, as well as Manning’s copyeditors, who touched up basicallyevery single paragraph in the book

Special thanks to the reviewers who took time out of their busy schedules to vide feedback on the manuscript at different stages during development Theyinclude Jason Rogers, Craig Smith, Emmanuel Asante, Chad Moone, Dr Jamie P Fin-lay, Dave Nicolette, Grant Oladipo, Jean-Philippe Castro, Americo Savinon, ThomasAthanas, Chris Kelly, Greg Vaughn, Pete Helgren, Joshua R Cronemeyer, Peter Melo,Robby O’Connor, Philip Hallstrom, Curtis Miller, Patrick Peak, Anthony J Topper,Brian Rose, Daniel Bretoi, Wesley Moxam, Jon Agnes, and David Workman

Finally, my friends and family have been amazing throughout my entire life, all theway from my parents—who supported my career choice in Ruby on Rails and techni-cal writing, even though they paid for me to study Network Admin at TAFE and alwaystold me that I should “get out the house more”—to my current housemate, whoaccepts that we don’t see much of each other (or at least I think so) You’re all won-derful people, and I hope now that the book is over I will see more of you I would listyou all here if only it didn’t require this book to be printed in a multivolume series

RYAN BIGG

Rails 3 in Action is a long-time coming To give you some perspective, the book was

originally called Merb in Action, and it managed a perpetual beta through the Merb

merge, the release of Rails 3.0, and is finally ready just in time for Rails 3.1

I can say with confidence that Rails 3 in Action would not exist without the hard,

tireless work of Ryan Bigg It was Ryan’s idea to focus the book around real-world

test-ing from the ground up, and it makes Rails 3 in Action the first book for Rails

practitio-ners that teaches Rails the way professional Rails developers do it

Trang 20

ACKNOWLEDGMENTS xix

Since we merged Merb with Rails, I have had the benefit of not insignificant port from friends and family, who helped keep me on course in the long process thateventually delivered Rails 3.0 I want to especially call out Aaron Patterson, José Valim,Santiago Pastorino, and Xavier Noria, who stepped up and brought life back to a com-munity that was starting to show signs of age by the time Rails 2.3 hit the shelves AndCarl Lerche, who helped me keep focus on doing things right, even when it wastempting not to

Finally, I would be remiss if I didn't thank my wife, Leah, who has been there for

me through the amazing trajectory of my development career, through good timesand bad Without her, I would have given up long ago

YEHUDA KATZ

Trang 21

about this book

Ruby on Rails is a leading web application framework built on top of the fantasticRuby programming language Both the language and the framework place anextreme emphasis on having a principle of least surprise and getting out of the way ofthe developers using it

Ruby on Rails has been growing at a rapid pace, with large internet companiessuch as Yellow Pages and Groupon using it for their core functionality With the latestrelease of Rails, version 3.1, comes a set of changes that improve the already brilliantframework that has been constructed over the past seven years The fantastic commu-nity around the framework has also been growing at a similar pace

This book is designed to take you through developing a full-featured Rails tion from step one, showing you exactly how professionals in the real world are devel-oping applications right now

applica-Who should read this book

This book is primarily for those who are looking to begin working with the Ruby onRails framework and who have some prior experience with Ruby, although that is notentirely necessary

Later chapters, such as chapter 13, “Designing an API,” chapter 17, “Engines,” andchapter 18, “Rack-based applications,” delve into more advanced topics, so these chap-ters are suitable for people who already have a foundation with Rails and are looking

to expand their skillset a little further

If you’re looking for a book that teaches you the same practices that are used inthe real world, then this is the book you are looking for

Trang 22

ABOUT THIS BOOK xxi

Chapter 5 begins an introduction to nested resources, building on top of the tures developed in the previous two chapters

Chapter 6 introduces authentication, requiring users to sign in to the applicationbefore they can perform certain tasks

Chapter 7 builds on the work in chapter 6 by adding new areas of the applicationthat are accessible only to users with a certain flag set in the database You also usenamespaces for the first time

Chapter 8 builds on the basic authorization created in chapter 7, fleshing it outinto something neater and more scalable

In chapter 9, you learn about file uploading using the Paperclip gem In this ter you also learn about testing parts of your application that use JavaScript and aboutCoffeeScript, a neater language that compiles down to JavaScript

Chapter 10 builds not one but two new features for the application, adding theability to comment on a ticket as well as track the ticket’s lifecycle through varyingstates

In chapter 11, you add a feature that lets users assign tags to tickets so they can beeasily grouped You also add a feature to allow users to search for tickets matching acertain state or tag, or both

Chapter 12 begins our foray into dealing with email in a Rails application You’llsee not only how to send email but also how to receive messages and parse them intomeaningful data in your application

Chapter 13 involves creating an API for the project resources in an applicationthat provide other applications with a standardized way to access your application’sdata We also look at token-based authentication and how to create multiple versions

of an API

In chapter 14, you deploy the application to an Ubuntu box and set it up to act like

a normal web server using a RubyGem called Passenger and a web server called nginx

In chapter 15, you create a “nice to have” feature: the ability to sign up or sign inusing either Twitter or GitHub When this is complete, people are no longer required

to provide you with an email and password when they sign up; instead, they can useGitHub and Twitter as authentication providers

Trang 23

By chapter 16, your application is all grown up and needs to handle any kind ofperformance issues it encounters We cover basic performance enhancements, such

as pagination, database indexing, and page and fragment caching

Chapter 17 introduces a new feature for Rails 3: engines You develop one of yourown from scratch—a forum system—and then integrate it with the existing application Chapter 18 delves into the depths of Rack, explaining how Rack applications aremade and can be tied into Rails The chapter also explains, and contains examples of,middleware being used in Rails

Code conventions and downloads

Code conventions in the book follow the style of other Manning books in the In Action

series All code in listings and in text appears in a monospaced font like this to rate it from ordinary text In some cases, the original source code has been reformat-ted to fit on the pages In general, the original code was written with page-widthlimitations in mind, but sometimes you may find a slight formatting differencebetween the code in the book and that provided in the source download In a few rarecases, where long lines could not be reformatted without changing their meaning, thebook listings contain line-continuation markers Code annotations accompany many

sepa-of the listings, highlighting important concepts In many cases, numbered bullets link

to explanations that follow in the text

Source code for all the working examples in this book is available for downloadfrom the publisher’s website at www.manning.com/Rails3inAction

Author Online

The purchase of Rails 3 in Action includes free access to a private forum run by

Man-ning Publications where you can make comments about the book, ask technical tions, and receive help from the authors and other users To access and subscribe tothe forum, point your browser to www.manning.com/Rails3inAction, and click theAuthor Online link This page provides information on how to get on the forum onceyou are registered, what kind of help is available, and the rules of conduct in theforum

Manning’s commitment to our readers is to provide a venue where a meaningfuldialogue between individual readers and between readers and the authors can takeplace It’s not a commitment to any specific amount of participation on the part of theauthors, whose contribution to the book’s forum remains voluntary (and unpaid) Wesuggest you try asking the authors some challenging questions, lest their interest stray! The Author Online forum and the archives of previous discussions will be accessi-ble from the publisher’s website as long as the book is in print

Trang 24

about the authors

RYAN BIGG has been developing Ruby on Rails since version 1.2 and can be foundhelping out the community by answering questions on IRC or StackOverflow or writ-ing documentation He currently works for a web consultancy based in Sydney calledRubyX

YEHUDA KATZ is well known not only for his work on this third version of Ruby onRails, but also for other web-related projects such as jQuery, Bundler, Merb, andSproutCore He currently works for Strobe in San Francisco as a lead developer on

SproutCore and is the coauthor of Manning’s jQuery in Action, Second Edition.

Trang 25

compen-us vividly of how culturally apart the world’s towns and regions were jcompen-ust 200 years ago.Isolated from each other, people spoke different dialects and languages In the streets

or in the countryside, it was easy to identify where they lived and what their trade orstation in life was just by their dress

Dress codes have changed since then and the diversity by region, so rich at thetime, has faded away It is now hard to tell apart the inhabitants of different conti-nents, let alone different towns or regions Perhaps we have traded cultural diversityfor a more varied personal life—certainly for a more varied and fast-paced technolog-ical life

At a time when it is hard to tell one computer book from another, Manning brates the inventiveness and initiative of the computer business with book coversbased on the rich diversity of regional life of two centuries ago, brought back to life byMaréchal’s pictures

Trang 26

Ruby on Rails, the framework

Welcome aboard! It’s great to have you with us on this journey through the world ofRuby on Rails Ruby on Rails is known throughout the lands as a powerful webframework that helps developers rapidly build modern web applications In partic-ular, it provides lots of niceties to help you in your quest to develop a full-featuredreal-world application and be happy doing it Great developers are happy develop-ers There’s much more to the Rails world than might appear at first glance, butnot overwhelmingly too much And what a first glance! Oh, you two haven’t met?Well, time for some introductions then!

This chapter covers

 Exploring Ruby on Rails

 Building the foundations of a Ruby on Rails app

 Working with the scaffold generator

Trang 27

1.1 What is Ruby on Rails?

Ruby on Rails is a framework built on the Ruby language, hence the name Ruby onRails The Ruby language was created back in 1993 by Yukihiro “Matz” Matsumuto ofJapan Ruby was released to the general public in 1995 Since then, it has earned both

a reputation and an enthusiastic following for its clean design, elegant syntax, andwide selection of tools available in the standard library and via a package management

system called RubyGems It also has a worldwide community and many active

contribu-tors constantly improving the language and the ecosystem around it

Ruby on Rails was created in 2004 by David Heinemeier Hansson during the opment of 37signals’ flagship product: Basecamp When Rails was needed for other37signals projects, the team extracted the Rails code from it, crafted the beginnings ofthe framework, and released it as open source under the MIT license.1 Since then,Ruby on Rails has quickly progressed to become one of the leading web developmentframeworks This is in no small part due to the large community surrounding it whoare constantly working on submitting patches to add new features or to fix existingbugs Version 3 of this framework indicates yet another significant milestone in theproject’s history and introduces some new concepts, but won’t leave those alreadyfamiliar with the framework in the dark The latest version of Rails is the primaryfocus of this book

devel-1.1.1 Benefits

Ruby on Rails allows for rapid development of applications by using a concept known

as convention over configuration When you begin writing a Ruby on Rails application,

you run an application generator, which creates a basic skeleton of directories andfiles for your application These files and directories provide categorization for pieces

of your code, such as the app/models directory for containing files that interact withthe database and the public/images directory for images Because all of this is alreadythere for you, you won’t be spending your time configuring the way your application islaid out It’s done for you

How rapidly can you develop a Ruby on Rails application? Take the annual Rails

Rumble event This event aims to bring together small teams of one to four developers

around the world to develop Ruby on Rails2 applications in a 48-hour period UsingRails, these teams can deliver amazing web applications in just two days.3 Anothergreat example of rapid development of a Rails application is the 20-minute blogscreencast recorded by Yehuda Katz.4 This screencast takes you from a no-applicationstate to having a basic blogging and commenting system

Ruby on Rails affords you a level of productivity unheard of in other web works because every Ruby on Rails application starts out the same way The similarity

frame-1 The MIT license: http://en.wikipedia.org/wiki/MIT_License.

2 And now other Ruby-based web frameworks, such as Sinatra.

3 To see an example of what has come out of previous Rails Rumbles, take a look at their alumni archive:

http://r09.railsrumble.com/entries.

4 20-minute blog screencast: http://vimeo.com/10732081.

Trang 28

What is Ruby on Rails?

between the applications is so close that the paradigm shift between different Railsapplications is not tremendous If and when you jump between Rails applications, youdon’t have to relearn how it all connects—it’s mostly the same

The core features of Rails are a conglomerate of many different parts called

Rail-ties (when said aloud it rhymes with “bowRail-ties”), such as Active Record, Active Support,

Action Mailer, and Action Pack.5 These different Railties provide a wide range of ods and classes that help you develop your applications They prevent you from per-forming boring, repetitive tasks—such as coding how your application hooks intoyour database—and let you get right down to writing valuable code for your business Ever wished for a built-in way of writing automated tests for your web application?

meth-Ruby on Rails has you covered with Test::Unit, part of meth-Ruby’s standard library It’s

incredibly easy to write automated test code for your application, as you’ll seethroughout this book Test::Unit saves your bacon in the long term, and that’s a fantas-tic thing We touch on Test::Unit in the next chapter before moving on to RSpec andCucumber, two other test frameworks that are preferred over Test::Unit and a littleeasier on the eyes too

In addition to testing frameworks, the Ruby community has produced several quality libraries (called RubyGems, or gems for short) for use in your day-to-day devel-opment with Ruby on Rails Some of these libraries add additional functionality toRuby on Rails; others provide ways to turn alternative markup languages such as Mark-down and Textile into HTML Usually, if you can think it, there’s a gem out there thatwill help you do it

Noticing a common pattern yet? Probably As you can see, Ruby on Rails (and thegreat community surrounding it) provides code that performs the trivial applicationtasks for you, from setting up the foundations of your application to handling thedelivery of email The time you save with all these libraries is immense! And becausethe code is open source, you don’t have to go to a specific vendor to get support Any-body who knows Ruby can help you if you’re stuck

In applications that don’t use MVC, the directory structure and how the differentparts connect to each other is commonly left up to the original developer Generally,

5 Railties share the same version number as Rails, which means when you’re using Rails 3.1, you’re using the 3.1 version of the Railtie This is helpful to know when you upgrade Rails because the version number of the installed Railties should be the same as the version number of Rails.

Trang 29

this is a bad idea because different people have different opinions on where thingsshould go In Rails, a specific directory structure makes all developers conform to thesame layout, putting all the major parts of the application inside an app directory.This app directory has three main subdirectories: models, controllers, and views.

Domain logic—how the records in your database are retrieved—is kept in models.

In Rails applications, models define the code that interacts with the database’s tables

to retrieve and set information in them Domain logic also means things such as dations or particular actions to perform on the data

Controllers interact with the models to gather information to send to the view.They call methods on the model classes, which can return single objects representingrows in the database or collections (arrays) of these objects Controllers then makethese objects available to the view through instance variables

Views display the information gathered by the controller, by referencing theinstance variables set there, in a user-friendly manner In Ruby on Rails, this display is

done by default with a templating language known as Embedded Ruby ( ERB) ERBallows you to embed Ruby (hence the name) into any kind of file you wish This tem-plate is then preprocessed on the server side into the output that’s shown to the user The assets, helpers, and mailers directories aren’t part of the MVC paradigm, butthey are important parts of Rails The assets directory is for the static assets of theapplication, such as JavaScript files, images, and Cascading Style Sheets (CSS) for mak-ing the application look pretty We look more closely at this in chapter 3

The helpers directory is a place to put Ruby code (specifically, modules) that vides helper methods for just the views These helper methods can help with complexformatting that would otherwise be messy in the view or is used in more than one place Finally, mailers is a home for the classes of your application that deal with sendingemail In previous versions of Rails, these classes were grouped with models but havesince been given their own home We look at them in chapter 11

pro-REST

MVC in Rails is aided by REST, a routing paradigm Representational State Transfer

(REST ) is the convention for routing in Rails When something adheres to this

conven-tion, it’s said to be REST ful Routing in Rails refers to how requests are routed within

the application itself You benefit greatly by adhering to these conventions, becauseRails provides a lot of functionality around RESTful routing, such as determiningwhere a form can, or will, send to

1.1.3 Rails in the wild

A question sometimes asked by people new to Rails is, “Is Rails ready?” Of course it is!The evidence is stacked mightily in Rails’ favor with websites such as Twitter, YellowPages, and of course Basecamp, serving millions and millions of page requests daily.6

6 Some of the more well-known applications that run on Ruby on Rails can be found at http://rubyonrails.org /applications

Trang 30

Developing your first application

If any site is a testament to the power of Ruby on Rails, Twitter is it Even thoughTwitter suffered from scaling problems back in 2008 (due to its massive growth and

other technological problems, not due to Rails), it is now the eleventh most popular

website, according to Alexa, and is exceptionally stable

Another well-known site that runs Ruby on Rails is GitHub, a hosting service forGit repositories This site was launched in February 2008 and is now the leading Gitweb-hosting site GitHub’s massive growth was in part due to the Ruby on Rails com-munity quickly adopting it as their de facto repository hosting site Now GitHub ishome to over a million repositories for just about every programming language on theplanet It’s not exclusive to programming languages either; if it can go in a Git reposi-tory, it can go on GitHub As a matter of fact, this book and its source code are kept onGitHub!

Now that you know what other people have accomplished with this framework,let’s dive into creating your own application

1.2 Developing your first application

We covered the theory behind Rails and showed how quickly and easily you candevelop an application Now it’s your turn to get an application going

rvm install 1.9.2

To use this version of Ruby, you would need to use rvm use 1.9.2 every time you wished

to use it or else set up a rvmrc file in the root of your project, which is explained on theRVM site in great detail Alternatively, you can set this version of Ruby as the defaultwith the command rvm use default 1.9.2, and use rvm use system if you ever want

to swap back to the system-provided Ruby install if you have one

If you’re on Windows, you can’t use RVM and you can’t use a 1.9.* version of Ruby,but that’s okay Rails 3 works with Ruby 1.8 versions of Rails too We would recom-mend the use of the Rails Installer program (http://railsinstaller.org) from EngineYard, or installing the Ruby 1.8.7-p352 binary from ruby-lang.org as an alternative

7 Broken Ubuntu Ruby explained here: http://ryanbigg.com/2010/12/ubuntu-ruby-rvm-rails-and-you/.

Trang 31

Next, you need to install the rails gem The following command installs bothRails and its dependencies If you’re using the Rails installer you will not need to runthis command because Rails will already be installed:

gem install rails -v 3.1.0

1.2.2 Generating an application

With Rails now installed, to generate an application, you run the rails command andpass it the new argument and the name of the application you want to generate:

things_i_bought When you run this command, it creates a new directory called

things_i_bought, which is where all your application’s code will go You can call yourapplication anything you wish, but it can’t be given the same name as a reserved word

in Rails For example, you wouldn’t call your application rails because it defines a Rails

constant, which is internal to Rails, and the two constants would clash.

The application that you’re going to generate will be able to record purchases youhave made You can generate it using this command:

rails new things_i_bought

The output from this command may seem a bit overwhelming at first, but rest assured:it’s for your own good All of the directories and files generated here provide thebuilding blocks for your application, and you’ll get to know each of them as we prog-ress For now, let’s get rolling and learn by doing, which is the best way of learning

1.2.3 Starting the application

To get the server running, you must first change into the newly created application’sdirectory and then run these commands to start the application server:

3000 on all network interfaces of this machine.8 To connect to this server, go tohttp://localhost:3000 in your favorite browser You’ll see the “Welcome aboard”page, which is so famous in Rails (see figure 1.1)

If you click About Your Application’s Environment, you’ll find your Ruby, Gems, Ruby on Rails, and Rack versions and other environmental data One of thethings to note here is that the output for Environment is Development Rails provides

Ruby-8 This is what the 0.0.0.0 address represents It is not an actual address, so to speak, and so localhost or 127.0.0.1 should be used.

Trang 32

Developing your first application

three environments for running your application: development, test, and production.How your application functions can depend on the environment in which it is run-ning For example, in the development environment, classes are not cached; so if youmake a change to a class when running an application in development mode, youdon’t need to restart the server, but the same change in the production environmentwould require a restart

1.2.4 Scaffolding

To get started with this Rails application, you generate a scaffold Scaffolds in Rails

pro-vide a lot of basic functionality but are generally not used for full-scale developmentbecause you may want something more customized, in which case you’d build it your-self But for this example of what Rails can do, let’s generate a scaffold by running thiscommand:

rails generate scaffold purchase name:string cost:float

When you used the rails command earlier, it generated an entire Rails application.You can use this command inside of an application to generate a specific part of theapplication by passing the generate argument to the rails command, followed bywhat it is you want to generate

Figure 1.1 Welcome aboard!

Trang 33

The scaffold command generates a model, a controller, and views based on thename passed after scaffold in this command These are the three important partsneeded for your purchase tracking The model provides a way to interact with a data-base The controller interacts with the model to retrieve and format its informationand defines different actions to perform on this data The views display the informa-tion from the controller in a neat format.

Everything after the name for the scaffold are the fields for the database table and

the attributes for the objects of this scaffold Here you tell Rails that the table for your

purchase scaffold will contain name and cost fields, which are a string and a float.9 To

create this table, the scaffold generator generates what’s known as a migration Let’s

have a look at what migrations are

devel-class CreatePurchases < ActiveRecord::Migration

Inside both of these methods you use database-agnostic commands to create anddrop a table In the up method, you create a table and specify the fields you want in

9 Usually you wouldn’t use a float for storing monetary amounts because it can lead to incorrect-rounding errors Generally, you store the amount in cents as an integer and then do the conversion back to a full dollar amount This example uses a float because it’s easier to not have to define the conversion at this point.

Listing 1.1 db/migrate/[date]_create_purchases.rb

Trang 34

Developing your first application

that table by calling methods on the t block variable The string and float methodscreate fields of those particular types on any Rails-compatible database system.10 Youspecified these fields when you used the scaffold command The timestampsmethod is special; it creates two fields called created_at and updated_at, which havetheir values set when records are created and updated automatically by Rails

To run the migration, type this command into the console:

rake db:migrate

This command run the self.up part of this migration Because this is your first timerunning migrations in your Rails application, and because you’re using a SQLite3database, Rails first creates the database in a new file at db/development.sqlite3 andthen creates the purchases table inside that When you run rake db:migrate, itdoesn’t just run the self.up method from the latest migration but runs any migrationthat hasn’t yet been run, allowing you to run multiple migrations sequentially

Your application is, by default, already set up to talk to this new database, so youdon’t need to change anything If you ever want to roll back this migration, you’d userake db:rollback, which rolls back the latest migration by running the self.downmethod of the migration.11

Rails keeps track of the last migration that was run by storing it using this line inthe db/schema.rb file:

ActiveRecord::Schema.define(:version => [timestamp]) do

This version should match the prefix of the migration you just created,12 and Rails usesthis value to know what migration it’s up to The remaining content of this file showsthe combined state of all the migrations to this point This file can be used to restorethe last-known state of your database if you run the rake db:schema:load command With your database set up with a purchases table in it, let’s look at how you canadd rows to it through your application

1.2.6 Viewing and creating purchases

Start your browser now and go to http://

localhost:3000/purchases You’ll see the

scaffolded screen for purchases, as shown in

figure 1.2 No purchases are listed yet, so

let’s add a new purchase by clicking New

Purchase

10 So far, MySQL, PostgreSQL, SQLite3, Oracle, Frontbase, and IBM DB.

11 If you want to roll back more than one migration, use the rake db:rollback STEP=3 command, which rolls back the three most recent migrations.

12 Where [timestamp] in this example is an actual timestamp formatted like YYYYmmddHHMMSS

Figure 1.2 Purchases

Trang 35

In figure 1.3, you see two inputs for the fields you generated This page is the result

of the new action from thePurchasesController controller What you see on the pagecomes from the view located at app/views/purchases/new.html.erb, and it looks likethe following listing

<h1>New purchase</h1>

<%= render 'form' %>

<%= link_to 'Back', purchases_path %>

This is an ERB file, which allows you to mix HTML and

Ruby code to generate dynamic pages The beginning of

an ERB tag indicates that the result of the code inside the

tag will be output to the page If you want the code to be

evaluated but not output, you use the <% tag, like this:

<% some_variable = "foo" %>

If you were to use <%= some_variable = "foo" %> here,

the some_variable variable would be set and the value

output to the screen By using <%=, the Ruby code is

eval-uated but not output

The render method, when passed a string as in this example, renders a partial A

partial is a separate template file that you can include in other templates to repeatsimilar code We’ll take a closer look at these in chapter 3

The link_to method generates a link with the text of the first argument (Back)and with an href attribute specified by the second argument (purchases_path),which is simply /purchases

This particular partial is at app/views/purchases/_form.html.erb, and the firsthalf of it looks like the following listing

Listing 1.3 First half of app/views/purchases/_form.html.erb

Figure 1.3 A new purchase

Trang 36

Developing your first application

This half is responsible for defining the form by using the form_for helper Theform_for method is passed one argument—an instance variable called @purchase—and with @purchase it generates a form This variable comes from the Purchases-Controller’s new action, which is shown in the following listing

The first line in this action sets up a new @purchase variable by calling the new method

on the Product model, which initializes a new object of this model The variable isthen automatically passed through to the view by Rails

Next in the controller is the respond_to method that defines what formats thisaction responds to Here, the controller responds to the html and xml formats Thehtml method here isn’t given a block and so will render the template from app/views/purchases/new.html.erb, whereas the xml method, which is given a block, will executethe code inside the block and return an XML version of the @purchase object You’ll

be looking at what the html response does from here forward because that is thedefault format requested

So far, all of this functionality is provided by Rails You’ve coded nothing yourself.With the scaffold generator, you get an awful lot for free

Going back to the view, the block for the form_for is defined between its do andthe %> at the end of the file Inside this block, you check the @purchase object for anyerrors by using the @purchase.errors.any? method These errors will come from themodel if the object did not pass the validation requirements set in the model If anyerrors exist, they’re rendered by the content inside this if statement Validation is aconcept covered shortly

The second half of this partial looks like the following listing

Trang 37

Here, the f object from the form_for block is used to define

labels and fields for your form At the end of this partial, the

submit method provides a dynamic submit button

Let’s fill in this form now and click the submit button You

should see something similar to figure 1.4

What you see here is the result of your posting: a successful

creation of a Purchase Let’s see how it got there The submit

button posts the data from the form to the create action, which looks like the ing listing

format.html { render :action => "new" }

format.xml { render :xml => @purchase.errors, :status => :unprocessabl e_entity }

end

end

end

Here, you use the Purchase.new you first saw used in the new action But this time you

pass it an argument of params[:purchase] params (short for parameters) is a method

that returns the parameters sent from your form in a Hash-like object When you pass

this params hash into new, Rails sets the attributes13 to the values from the form Inside the respond_to is an if statement that calls @purchase.save This method

validates the record, and if it’s valid, the method saves the record to the database and

returns true

If the return value is true, the action responds by redirecting to the new

@purchase object using the redirect_to method, which takes either a path or anobject that it turns into a path (as seen in this example) The redirect_to methodinterprets what the @purchase object is and determines that the path required ispurchase_path because it’s an object of the Purchase model This path takes you tothe show action for this controller The :notice option passed to the redirect_to sets

up a flash message A flash message is a message that can be displayed on the next

Trang 38

Developing your first application

should note here that this doesn’t call the new action/method again14 but only ders the template

You can make the creation of the @purchase object fail by adding a validation.Let’s do that now

Let’s test out these validations by going back to http://localhost:3000/purchases,clicking New Purchase, and clicking Create Purchase You should see the errors shown

in figure 1.5

14 To do that, you call redirect_to new_purchase_path , but that wouldn’t persist the state of the

@purchase object to this new request without some seriously bad hackery By rerendering the template, you can display information about the object if the object is invalid.

Listing 1.7 app/models/purchase.rb

Figure 1.5

Errors on purchase

Trang 39

Great! Here, you’re told that Name can’t be blank and that the value you entered forCost isn’t a number Let’s see what happens if you enter foo for the Name field and-100 for the Cost field, and click Create Purchase You should get a different error forthe Cost field now, as shown in figure 1.6.

Good to see! Both of your validations are working now When you change Cost to

100 and click Create Purchase, it should be considered valid by the validations andtake you to the show action Let’s look at what this particular action does now

1.2.8 Showing off

This action displays the content such as shown in figure 1.7

The number at the end of the URL is the unique numerical ID for this purchase Butwhat does it mean? Let’s look at the view for this show action now, as shown in the fol-lowing listing

Trang 40

Developing your first application

<%= @purchase.cost %>

</p>

<%= link_to 'Edit', edit_purchase_path(@purchase) %> |

<%= link_to 'Back', purchases_path %>

On the first line is the notice method, which displays the notice set on theredirect_to from the create action After that, field values are displayed in p tags bysimply calling them as methods on your @purchase object This object is defined inyour PurchasesController’s show action, as shown in the following listing

Going back to the view (app/views/purchases/show.html.erb) now, at the end ofthis file you see link_to, which generates a link using the first argument as the textfor it and the second argument as the href for that URL The second argument forlink_to is a method itself: edit_purchase_path This method is provided by amethod call in config/routes.rb, which we now look at

1.2.9 Routing

The config/routes.rb file of every Rails application is where the application routes aredefined in a succinct Ruby syntax The methods used in this file define the pathwaysfrom requests to controllers If you look in your config/routes.rb while ignoring thecommented-out lines for now, you’ll see what’s shown in the following listing

ThingsIBought::Application.routes.draw do

resources :purchases

end

Inside the block for the draw method is the resources method Collections of similar

objects in Rails are referred to as resources This method defines the routes and routing

helpers (such as the edit_purchase_path method) to your purchases resources Look

at table 1.1 for a list of the helpers and their corresponding routes

In this table, :id can be substituted for the ID of a record Each routing helper has

an alternative version that will give you the full URL to the resource Simply use the_url extension rather than _path, and you’ll get a URL such as http://localhost:3000/purchases for purchases_url

Listing 1.9 app/controllers/purchases_controller.rb

Listing 1.10 config/routes.rb

Ngày đăng: 28/04/2014, 16:55

Xem thêm

TỪ KHÓA LIÊN QUAN