0321501748 cashion sec1-3 issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be...

15
The following is an excerpt from a Short Cut published by one of the Pearson Education imprints. Short Cuts are short, concise, PDF documents designed specifically for busy technical professionals like you. We’ve provided this excerpt to help you review the product before you purchase. Please note, the hyperlinks contained within this excerpt have been deactivated. Tap into learning—NOW! Visit www.informit.com/shortcuts for a complete list of Short Cuts. Your Short Cut to Knowledge sh o rt cut

Upload: others

Post on 19-Jul-2020

7 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

The following is an excerpt from a Short Cut published by one of the Pearson Education imprints.

Short Cuts are short, concise, PDF documents designed specifically for busy technical professionals like you.

We’ve provided this excerpt to help you review the product before you purchase.Please note, the hyperlinks contained within this excerpt have been deactivated.

Tap into learning—NOW!

Visit www.informit.com/shortcuts for a complete list of Short Cuts.

Your Short Cut to Knowledge

shortcut

Page 2: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

Rails Refactoring to Resources

Using CRUD and REST in Your Rails Application

Addison-Wesley Professional Ruby Series

shortcut

Trotter Cashion

www.awprofessional.com/ruby

Section 1:What This Short Cut Covers . . . . . . 3

Section 2:What Is REST? . . . . . . . . . . . . . . . . . . . 6

Section 3:Refactorings . . . . . . . . . . . . . . . . . . . 10

Section 4:RESTful Controllers . . . . . . . . . . . . . 31

Section 5:RESTful Routes . . . . . . . . . . . . . . . . . 48

Section 6:RESTful Views . . . . . . . . . . . . . . . . . . 54

Section 7:RESTful Tests . . . . . . . . . . . . . . . . . . . 59

Section 8:RESTful Authentication . . . . . . . . . 61

Section 9:Consuming RESTful APIs . . . . . . . . 63

Resources . . . . . . . . . . . . . . . . . . . . . . 72

About the Author . . . . . . . . . . . . . . 73

Page 3: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 1

What This Short Cut Covers

This short cut shows you how to incorporate the changes thatRepresentational State Transfer, better known as REST, has brought toRails in your application. It starts off slowly with an introduction to theshort cut as a whole and a look at the benefits of REST. It then buildsmomentum with three refactorings that are essential in any Rails devel-oper’s toolkit. From there, we look at the changes that REST has broughtto Rails, focusing on specific pieces of Rails one at a time. Finally, wefinish with a look at the consumption of RESTful APIs usingActiveResource and the venerable cURL. Learning new programmingparadigms is always tricky, and REST is no exception. I hope this shortcut makes your transition a little easier. If you have any questions, orwould just like to let me know how much the short cut sucks (hopefullynot many feel this way), email me at [email protected].

Representational State Transfer, better known as REST, is an architectureformulated by Roy Fielding during his work on the HTTP specification.In his PhD dissertation [Fielding], he put the REST architecture intowords, explaining both its benefits and shortcomings. To summarize hisdissertation, REST is the use of URLs to represent conceptual resources,

3

Section 1:What This Short Cut Covers

1.1 Target Audience . . . . . . . . . . . . . . . . . . . . . . 5

1.2 Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

Page 4: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

What This Short Cut Covers

physical representations of which can be retrieved through content type negotiation. So,http://wesellinfo.example/top-ten-books will always return the top-ten books, and content typenegotiation will be used to determine whether that list is returned as HTML, XML, or some otherformat. Though REST involves more than merely content type negotiation and conceptualresources, this short cut will not attempt to thoroughly defend REST. Instead, I will assume that youare either already convinced or intrigued enough to want to use some of the idioms that REST isinjecting into the Rails culture.

Regardless of your feelings about REST, the refactorings that I detail in the beginning of this shortcut can help create a better application. The first two (respond_to and crud) do not require thatyou adopt REST. The third (resource) requires only that you use Rails’s REST concept in onecontroller and is helpful for deciding whether REST feels right to you. These refactorings will helpyou clean your application code using small, easy-to-follow steps that minimize the number offailing tests you experience during the process.

The remaining content in this short cut is divided into sections that correspond to the parts ofRails that the RESTful mind-set touches. Though not all the information requires that you adoptREST, it does support the use of REST in Rails.

4 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.

Page 5: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 1

1.2 Rails

1.1 Target AudienceThis short cut is written for the developer who is already familiar with performing basic tasks inRails. A few sections, marked accordingly, involve in-depth Ruby magic. The novice can skip themore difficult sections without missing any of the core concepts this short cut addresses. However,careful study of the more difficult sections, possibly with help from the Pickaxe Book [Thomas],will greatly increase the novice’s appreciation of Ruby and Rails.

1.2 RailsMost of the information in this short cut is written on the assumption that you are using Rails 1.2.If you cannot upgrade to Rails 1.2 for any reason, the first two refactorings will still be useful toyou. However, some pieces will not work, so be sure to have good tests to let you know if any ofyour changes cause your application to break. Hopefully, you’re using Subversion so that thesemistakes do no irreparable harm.

5 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.

Page 6: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

Section 4:RESTful Controllers

4.1 A RESTful Controller . . . . . . . . . . . . . . . . . 31

4.2 Automating RESTful Controller Generation . . . . . . . . . . . . . . . 34

4.3 respond_to . . . . . . . . . . . . . . . . . . . . . . . 40

4.4 How Content Type Negotiation Works . . . . . . . . . . . . . . . . . . 46

SECTION 4

RESTful Controllers

4.1 A RESTful ControllerWhen writing RESTful Rails applications, the unifying theme is theCRUD controller architecture, which dictates that controllers have thefollowing methods with corresponding URLs.

class TasksController < ApplicationController

def index; end # /tasks

def new; end # /tasks/new

def create; end # /tasks

def show; end # /tasks/1

def edit; end # /tasks/1;edit

def update; end # /tasks/1

def destroy; end # /tasks/1

end

Of course, the preceding code references multiple actions at one URL,something that cannot be done without RESTful Rails. Multiplemethods on one URL are accomplished with the new map.resourcescommand in routes.rb. This command enables method choice, not

31

Page 7: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 4

4.1 A RESTful Controller

just on URL, but also on HTTP method type, using the four methods: GET, POST, PUT, and DELETE.3

Therefore, the previous controller’s routes look more like the following.

class TasksController < ApplicationController

def index; end # GET /tasks

def new; end # GET /tasks/new

def create; end # POST /tasks

def show; end # GET /tasks/1

def edit; end # GET /tasks/1;edit

def update; end # PUT /tasks/1

def destroy; end # DELETE /tasks/1

end

Each HTTP method and route combination is unique, which allows routes.rb to choose the appro-priate method to handle the request. It is important to understand why each HTTP method is usedin each circumstance. GET is used to retrieve a resource; POST is used to create a resource; PUT is usedto update a resource; and DELETE is used to remove a resource. When using GET, we should expectno change to the data in our database. All other methods should result in a change to data.

When developing a large RESTful Rails application, all controllers tend to assume the same basicshape.

class TasksController < ApplicationController

def index

@tasks = Task.find(:all)

end

32 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.

3 Major browsers do not currently support HTTP methods other than POST or GET. The Rails method of faking PUT and DELETE is explained in moredetail in Section 5.2.

Page 8: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 4

4.1 A RESTful Controller

def new

@task = Task.new

end

def create

@task = Task.new(params[:task])

if @task.save

redirect_to :action => :show, :id => @task.id

else

render :action => :new

end

end

def show

@task = Task.find(params[:id])

end

def edit

@task = Task.find(params[:id])

end

def update

@task = Task.find(params[:id])

if @task.update_attributes(params[:task])

redirect_to :action => :show, :id => @task.id

else

33 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.

Page 9: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 4

4.2 Automating RESTful Controller Generation

render :action => :new

end

end

def destroy

@task = Task.find(params[:id])

@task.destroy

render :action => :index

end

end

4.2 Automating RESTful Controller GenerationAlthough simple to do, writing RESTful controllers by hand is time consuming. Rather than letprogrammers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers.Rails provides two resource generators, similar to the scaffolding generator that ships with Rails.Ruby, through inheritance, allows us to inherit from a CrudController class that contains basic RESTfunctionality. Both of these methods require adding the necessary resource to routes.rb by hand.

4.2.1 The Resource GeneratorsRails provides two similar resource generators. The first, scaffold_resource, generates full scaffoldingof model, view, helper, tests, and controller for a resource. As arguments, it takes the model name (insingular form) and an optional list of property names and data types for the model. Thescaffold_resource generator is run using

ruby script/generate scaffold_resource task name:string description:text due_date:date

34 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.

Page 10: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 4

4.2 Automating RESTful Controller Generation

The second generator, resource, provides the same functionality as scaffold_resource, but does not create any views. Its syntax is identical to the scaffold_resource syntax. The resource generator is useful when views written by scaffold_resource will be overwritten immediately with customviews.

Both generators create controller code that is similar to the code shown earlier in theTasksController. In addition, the generators create a model with an appropriate migration tocreate the fields specified in the command line. These two tools are useful for cranking out manyskeleton resources at the beginning of a project.

4.2.2 The CrudControllerThe repetition in RESTful controllers is readily apparent. For this reason, Jake Howerton created acentral CRUD controller from which all his controllers inherit. Through creative use of meta-programming, this controller greatly simplifies your application. A light variation on his originaldesign follows.4

class CrudController < ApplicationController

before_filter :find_object, :only => [:show, :edit, :update, :destroy]

def index

instance_variable_set(“@#{controller_name.pluralize}”, current_model.find(:all))

end

35 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.

4 Though messaging is left out of the CrudController, often it is not necessary because the page to which the user returns is their created orupdated object, or a list of objects with their deleted object missing. If messaging is required, you can implement it in your subclassed controller usingafter-filters.

Page 11: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 4

4.2 Automating RESTful Controller Generation

def new

set_singular(current_model.new)

end

def create

set_singular(current_model.new(params_hash))

if get_singular.save

redirect_to :action => :show, :id => get_singular.id

else

render :action => :new

end

end

def show

end

def edit

end

def update

if get_singular.update_attributes(params_hash)

redirect_to :action => :show, :id => get_singular.id

else

render :action => :edit

end

end

36 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.

Page 12: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 4

4.2 Automating RESTful Controller Generation

def destroy

get_singular.destroy

redirect_to :action => :index

end

private

def find_object

set_singular(current_model.find(params[:id]))

end

def current_model

Object.const_get controller_name.singularize.classify

end

def params_hash

params[controller_name.singularize.to_sym]

end

def set_singular(rvalue)

instance_variable_set(“@#{controller_name.singularize}”, rvalue)

end

def get_singular

instance_variable_get(“@#{controller_name.singularize}”)

end

end

37 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.

Page 13: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 4

4.2 Automating RESTful Controller Generation

Putting this code into lib/crud_controller.rb allows TasksController to become the following.

class TasksController < CrudController

end

Your controllers are now dead simple. In fact, you will find that many of your controllers begin tolook like the preceding code, with only those that need extra functionality redefining the methodsfrom CrudController.

4.2.3 BelongsToCrudControllerAnother version of the CrudController is the BelongsToCrudController. The BelongsToCrudControlleris used when the model belongs to another model, and the belongs_to association is required. Thefollowing code explains this more clearly.

class BelongsToCrudController < CrudController

before_filter :find_parent

def index

instance_variable_set(“@#{controller_name.pluralize}”, get_parents_children)

end

def create

set_singular(current_model.new(params_hash))

if get_singular.save

get_parents_children << get_singular

redirect_to :action => :show, :id => get_singular.id

else

38 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.

Page 14: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 4

4.2 Automating RESTful Controller Generation

render :action => :new

end

end

private

def self.parent_model(klass)

define_method(:parent_model) { klass }

private :parent_model

end

def find_parent

if get_singular

get_singular.send(parent_model.table_name.singularize.to_sym).id

else

params[:”#{parent_model.table_name.singularize)_id”]

end

set_parent(id)

end

def set_parent(rvalue)

instance_variable_set(“@#{parent_model.table_name.singularize}”, rvalue)

end

def get_parent

instance_variable_get(”@#{parent_model.table_name.singularize}”)

end

39 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.

Page 15: 0321501748 Cashion Sec1-3 Issptgmedia.pearsoncmg.com/images/9780321501745/... · programmers be wasteful, Rails and Ruby provide ways to automate creating RESTful controllers. Rails

SECTION 4

4.3 respond_to

def get_parents_children

get_parent.send(controller_name.pluralize.to_sym)

end

end

With the preceding code in /lib/belongs_to_crud_controller.rb, a TaskController with parentprojects looks like

class TasksController < BelongsToCrudController

parent_model Project

end

Other than the parent_model method called in the child class controller, using BelongsToCrudControlleris similar to using the CrudController.

4.3 respond_toContent type negotiation, which is discussed in more detail in Section 4.4, is a critical componentof RESTful design. Because each URL represents a conceptual resource, not its physical manifesta-tion, content type negotiation is necessary to retrieve the appropriate document. Web browserswant HTML; however, many other users and agents want RSS or other varieties of XML.

To manage content type negotiation, Rails provides the respond_to method. For those interested insource diving, this method is found in actionpack/lib/action_controller/mime_responds.rb. Forthose not interested in digging through code, respond_to is a method called from your controllersthat takes either a block or a list of content types. The block format, which takes a block thatdefines actions to perform for each content type, is used most frequently.

40 Rails Refactoring to ResourcesBy Trotter Cashion

© 2007, Pearson Education, Inc. All rights reserved.This publication is protected by copyright. Please see page 2 for more details.