Edge Rails 的更新: Activesource中的custom method

Posted by yudi
on Thursday, December 20


近日 ActiveResource 进行了重大升级,使其不必通过后台URI的支持即可以激活custom method。令我感到非常激动的不仅仅是自己对 ARes1的热爱,也是因为这是我在 Rails Hackfest活动 提交的补丁之一。当初提交的代码中仍有许多不确定的地方,所以我自己也不太清楚它是否能被采纳。值得感谢的是,它被采取了。那么关于我就说到这儿,下面让我们一起来谈谈你。

说道您已经拥有一个具备REST结构的网络服务。它具备着您为 Person资源 所准备的建立在CRUD之上的action,包括几个特别的 custom method,例如 promote, deactivate 和一个定制搜集method: sort。如果没有来自ARes的custom method支持,您就得亲手建立起您所需要的URI,并且要亲自设定用来激活method的http连接。

的确,这样做比较累人。下面进入custom method支持。

首先假设有下得到支持的远程服务:

1
2
3
4
5
6
# Collection custom method
GET /people/sorted.xml?by=sort_field

# Element custom methods
PUT /people/1/promoted.xml?position=position_name
DELETE /people/1/deactivated.xml

这里是我们简单定义的 ARes Person 类:

1
2
3
class Person < ActiveResource::Base
  self.site = "http://mypeeps.com/"
end

ARes里激活定制method的格式其实蛮简单的。只需要在类2或对象实体3使用get, post, put或delete之一4来组成您需要的http method。将需要激活的定制method名称作为第一个实参(argument),其他需要输入的形参(parameter)放到一起作为第二个实参(argument)。让我为上述恼人的描述举个例子:

既然已经拥有美妙的远程REST服务,我们可以:

ActiveResource Collection Custom Method Calls


我们使用collection call来针对资源collection。简单来说,collection call可以是任何一个不对当前资源进行操作的method call。它们的URI并不涉及资源id,使得它们能够得到简便的维护。

一个定制的method call不属于您通过设置RESTFUL路由后直接得到的CRUD 行为。在我们的示例中,我们有一个叫做sorted 的 collection custom method。这个method输出针对个别域搜索资源而得到的结果。5

远程服务支持下面的URI:

1
2
# Collection custom method
GET /people/sorted.xml?by=sort_field

下面是如何通过 ARes1 激活定制method:

1
2
3
# 获取按照名字排列的职员列表
people = Person.get(:sorted, :by => 'first_name') # =>
   # GET /people/sorted.xml?by=first_name

如果您的公司经营变得困难,而且您有一个被远程服务支持的使用put方法的 layoff REST 行为,下面是您的表达式:

1
2
# 解雇所有人
Person.put(:layoff) # => PUT /people/layoff.xml

希望现在您已经了解首先需要通过ARes1类激活使用远程服务的Http方法,并使用custom method的名称作为第一个实参(:layout)。非常简单。针对类使用的 custom method 被称为 collection method (由于它不引用已经存在的资源6),并且为资源集建立了合适的 URI

ActiveResource Element Custom Method Calls


如果您需要操作某一特定的资源,您将需要激活element call。在ARes1中,collection custom method 与 element custom method 之间唯一的区别在于 使用element call的时候,您所操作的对象是 ARes model 的一个实体。被建立的URI则参照特定的资源而进行调整。在我们的示例中:

远程服务现在支持下面的URI:

1
2
# 通过 Element custom method 使某人晋升到指定的职位
PUT /people/1/promoted.xml?position=position_name

下面是您如何通过 ARes 激活这个method:

1
2
3
4
# 提升我们的明星开发员
ryan = Person.find(1)
ryan.put( :promoted, :position => 'Manager')  # 嗯。。这对我是真正的提升吗??
    # PUT /people/1/promoted.xml?position=Manager

远程服务需要的是同 PUT http方法 一同使用的晋升方法 (promoted call),所以您唯一需要做得是在即将得到晋升的 Person 实体上激活 PUT 方法,以及包括了晋升细节的 hash 数组。同样,对于删除 (delete):

在服务器上:


DELETE /people/1/deactivated.xml

在 ARes 中…

1
2
3
# 结果他变得非常非常受欢迎 (不能留他在这里了)
ryan = Person.find(1)
ryan.delete( :deactivated)  # DELETE /people/1/deactivate.xml

后记


值得一提的一件事是除了 GET 以外所有 custom method call 都会输出来自远程服务的回应。您可以根据这些回应代码来设置您自己的回应。GET 输出一个 hash数组7 ,这个数组用来表达 来自远程服务的XML数据。如果您需要通过 GET 获取实际的对象,可以使用 FIND 方法并输入一个符号:

1
2
3
4
# 获取所有的经理 (managers)
Person.get( :managers) #=> [{:name => "Ryan"}, {:name => "David"}]
Person.find( :managers) #=> <#Person...><#Person ...>
   #=> GET /people/managers.xml

ActiveResource 的 custom method,现在是你的了

注脚:

1Active Resource本身,文中皆简称 ARes

2针对定制搜集的method

3上面提到的特殊定制的methods

4也被称之为http动词,译者注

5在我原先提交的示例中叫做sort,后来经DHH建议修改为形容词sorted。您会发现这样做是为了使URI以及ARes1 表达式读起来更加接近琅琅上口的句子

6 已经被记录在数据库的资源:

1
2
person = Person.new # person is NOT an existing resource
person.save #=> true # person IS an existing resource
谢谢 Ryan 的例子!

7[{1=>”Ryan” },{2=>”David”}]


原文作者是 Ryan Daigle, 请访问他的博客
本片译文的原文地址:http://ryandaigle.com/articles/2007/4/26/what-s-new-in-edge-rails-activeresource-gets-custom-methods

Comments

Leave a response

  1. drive2meDecember 24, 2007 @ 12:52 AM

    很好!