Advanced Rails Recipe ( 一 )

Create a RESTful Resource
Problem
You’ve heard all the buzz about creating RESTful this and that. There’s
little doubt that Rails 2.0 heavily favors the REST architectural style1
and that it will continue to do so.
You’re feeling a little out of the loop, and what you’ve heard so far is
a tad too academic. As a practical matter, you’d like to create a web-
accessible API for one of your models and write a client program to
administer that model remotely. What can resources do for you?
Solution
Let’s forget about REST for a moment and try to solve a problem. Sup-
pose we organize events and we want a web-based interface for creating,
reading, updating, and deleting events (affectionately known as CRUD).
The first part of the solution comes in a single command, but what it
does can be confusing. The scaffold generator churns out all the CRUD
support code for administering events in a RESTful way.2 We’ll put up
event scaffolding in one fell swoop:
$ script/generate scaffold event name:string description:text  ֓
capacity:integer price:decimal starts_at:datetime
That single command generates a bunch of code: a model, a controller
with no fewer than seven actions, view template files for actions that
need them, tests, and even a migration file with the database columns
we listed on the command line.
Next, we just need to create the database and apply the migration:
$ rake db:create
$ rake db:migrate
That’s all there is to it! Fire up the application, and, lo and behold, we

now have a full HTML interface to CRUD (the verb form) events.


Before we move on to the second part of the solution, let’s dive a bit
deeper to see what just happened. In some ways, it’s just like the old
Rails scaffolding, but there’s a significant twist. You may have noticed
that the following line was added to our config/routes.rb file:
map.resources :events
That line is the key ingredient to our RESTful application. It dynam-
ically creates a set of named RESTful routes for accessing our events
(called resources) via URLs. The routes map to the seven actions in our
controller: index, show, new, create, edit, update, and destroy.
The best way to see what’s going on behind the scenes is to print out
all the defined routes by typing this:
$ rake routes
Let’s look at a few just to get a taste of how this works (you’ll see more in
your output). First, we have routes for dealing with the events collection:
events GET /events {:controller=>"events", :action=>"index"}
POST /events {:controller=>"events", :action=>"create"}
The leftmost column gives the name of the route (events), followed by
the matching HTTP verb and URL path, and then the action/controller
pair that the route ends up invoking. So, to list all our events—the
index action—we would issue an HTTP GET request to the URI /events.
Then, inside our application, we use the events_url route helper to gen-
erate the full URL for listing events. (Alternatively, you can use the
events_path method to just get the path part of the URL, often referred
to as the URI.)
Notice that the same incoming URL path is mapped to our create action.
The only difference is the HTTP verb that’s used: GET is a read-only
operation that lists the events, and POST is a write operation that cre-
ates a new event.
We also have RESTful routes for dealing with a specific member of the
events collection:
event GET /events/:id {:controller=>"events", :action=>"show"}
PUT /events/:id {:controller=>"events", :action=>"update"}
In these cases, the name of the route is singular (event) because it’s
dealing with one particular event. Again, the URL path is the same for
both actions. The HTTP verb is used to disambiguate whether we want
to read or update a single event by its primary key (the :id route param-
eter). Inside our application, we use the event_url(@event) route helper,


for example, to generate a URL to show our event. Passing @event to
the route helper will automatically fill in the :id route parameter with
the ID of the event.
So, in a nutshell, the map.resources line generates RESTful routes into
our application based on both the incoming URL path and an HTTP
verb. Now, browsers generally issue GET and POST requests, leaving
the other HTTP verbs to the academics. So, how do we tell our appli-
cation that we want to update an existing event (the PUT verb) or to
delete an event (the DELETE verb)? Well, that involves a few more new
conventions.
If we have an @event model object (and it’s declared to be a resource),
then in our new.html.erb and edit.html.erb forms, we can simply use this:
Download Rest/app/views/events/new.html.erb
<% form_for @event do |f| -%>
The form_for will generate the appropriate form tag depending on the
state of the @event object. If it’s a new record that hasn’t yet been saved,
Rails knows that it needs to be created. So, the form_for generates a form
tag that looks like this:
<form action="/events" method="post" >
This form will post to our create action because, according to the REST-
ful routing conventions, the HTTP verb and URL path map to that
action.
However, if the event is an existing record that has previously been
saved, then Rails knows we’re trying to update it. In this case, the form
should post to the update action. To do that, the form_for method slaps
in a hidden field to simulate a PUT operation. This in turn triggers
the proper RESTful route when Rails intercepts the request. It looks
something like this in the generated form:
<form action="/events/1" method="post" >
<input name="_method" type="hidden" value="put" />
OK, so at the end of all this, we’re still administering events in the
browser, just with special URLs. The immediate upshot is we can turn
any of our models into resources—events, registrations, users, and so
on—and then administer them through a consistent URL scheme. It’s
just one more example of Rails conventions removing guesswork.
Now let’s move on to the second part of the solution. Let’s say we’d like
to write a client program to administer events remotely. We’ll have our


client program speak XML back and forth with our Rails application
(imagine what that must sound like!). To do that, let’s turn our atten-
tion to the scaffold-generated index action in our EventsController. It has
all the familiar stuff, plus a respond_to block:
Download Rest/app/controllers/events_controller.rb
def index
@events = Event.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @events }
end
end
The action starts by setting up a collection of events. The respond_to
block determines how those events are rendered based on which for-
mat the client requests. By default, browsers prefer the HTML format.
In that case, the index action renders the index.html.erb template to gen-
erate an HTML response.
However, the index action also responds to requests for events in an
XML format. To get the collection of events as XML, we just need our
client program to issue a GET request with .xml tacked to the end of the
URL, like this:
http://localhost:3000/events.xml
Here’s where things get interesting. We already have a consistent way
to administer our events using the RESTful URL conventions. And we
already have a way to vary how the events are represented using the
respond_to block in actions.
Therefore, we already have a web-accessible API to our event resources.
All we need to do is write a client program to administer our events
remotely. Active Resource makes that really easy.
First, we write a stand-alone Ruby program: the Active Resource client.
(I typically put these in a services directory, but they could live any-
where.) It doesn’t need to load Rails per se, but we do need to require
the activeresource gem:
Download Rest/services/event_client.rb
require 'rubygems'
require 'activeresource'


Then we create an Event proxy class that points to the server where the
event resources live:
Download Rest/services/event_client.rb
class Event < ActiveResource::Base
self.site = "http://localhost:3000"
end
Active Resource now knows how to build URLs for accessing our event
resources, and it’ll push XML over HTTP until the cows come home.
Indeed, here’s where having an application that responds to XML really
shines. All the standard CRUD-level operations are available, as if our
proxy class were a real Active Record model.
Next, we’ll find all the events and print their names:
Download Rest/services/event_client.rb
events = Event.find(:all)
puts events.map(&:name)
Then we’ll find a specific event and update its attributes:
Download Rest/services/event_client.rb
e = Event.find(1)
e.price = 20.00
e.save
Finally, we’ll create and delete an event:
Download Rest/services/event_client.rb
e = Event.create(:name => "Shortest event evar!" ,
:starts_at => 1.second.ago,
:capacity => 25,
:price => 10.00)
e.destroy
Before we run the client, we’ll configure a logger to see what happened
behind the scenes by adding this line before the Event class definition:
Download Rest/services/event_client.rb
ActiveResource::Base.logger = Logger.new("#{File.dirname(__FILE__)}/events.log" )
Then, to run the client, we just use this:
$ ruby event_client.rb
Here’s the output in the events.log file, which can be quite handy for
debugging an ornery client:
GET http://localhost:3000/events.xml
--> 200 OK (<?xml version="1.0" encoding="UTF-8"?> ...


GET http://localhost:3000/events/1.xml
--> 200 OK (<?xml version="1.0" encoding="UTF-8"?> ...
PUT http://localhost:3000/events/1.xml
--> 200 OK ( b 0.11s)
POST http://localhost:3000/events.xml
--> 201 Created (<?xml version="1.0" encoding="UTF-8"?> ...
DELETE http://localhost:3000/events/12.xml
--> 200 OK ( b 0.11s)
Now we have a full API for creating, reading, updating, and deleting
events via the browser or a remote client program. And we have conven-
tions: a consistent set of URLs that map to a consistent set of actions.
This generally makes deciding where things go a lot easier. In particular,
we no longer have controllers that are dumping grounds for spurious
actions.
Discussion
It is important to note here that REST (map.resources in particular)
and respond_to blocks are orthogonal. You can use respond_to without
resources, and vice versa.
Although Active Resource ships with Rails and uses some of its support
classes, it’s not necessarily Rails-specific. You can use it to reach out
to any server supporting the RESTful conventions of Rails.
Also See
The map.resources method generates routes only for the seven CRUD
actions. This begs the question, how do I call actions outside of this
set? Recipe 2, Add Your Own RESTful Actions, on the following page
shows how to customize the routes for application-specific concerns.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值