December 12, 2006 @ 10:32 AM

Taking ARes Out For a Test Drive

Although ActiveResource was announced last June during David’s World of Resources talk at RailsConf, it has yet to see an official release. It currently lives in the rails svn trunk with the rest of Rails, but was left out in the 1.2 Pre Release. A few rails developers (myself included) have been plugging away at it little by little as we’ve been implementing little REST services. (The only public example I know of is Blinksale, which uses what looks like a compatible interface. However, they provide their own REST::Client library as a sample ruby client lib, instead of ARes). From what I gather, ARes is only being used in limited, private services, but I think it’s time to get it out in the open. My goal with this (and possibly more, making this a series of articles) is to get the word out on where we’re at with ActiveResource, and hopefully get some folks interested in helping out.

For those that don’t know, ActiveResource is a client-side XML consumer for APIs created by the latest Rails restful additions. Consider it your reward for figuring out how to wield map.resources appropriately and restructuring parts of your app around it. That’s right, follow these rules, and you’ll get most of a server API and a client library for free.

Installation

Since ActiveResource isn’t released, how do we start playing with it? Probably the easiest way (until a gem is released) is by checking out the whole rails trunk and requiring both ActiveSupport and ActiveResource:

$ svn co http://dev.rubyonrails.org/svn/rails/trunk 
$ irb
> require 'activesupport/lib/active_support'
> require 'activeresource/lib/active_resource'

Note: if you don’t already have a checkout of the rails trunk somewhere, all you actually need are ActiveSupport and ActiveResource.

Building a Client API Library for Beast

If you’re still following along with us in irb, you can go ahead and create the ActiveResource classes and start using it. First, we’ll create a base class that will set up the Beast site URL, as well as the optional user/password if you want to make changes.

1
2
3
4
5
6
class BeastResource < ActiveResource::Base
  # any recent trunk version of Beast will work here
  self.site = 'http://beast.caboo.se'
  # site.user = 'rick'
  # site.password = 'secret sauce'
end

Now that we have that, we can create classes for the four main resources we’ll be dealing with: users, forums, topics, and posts. Users and forums will be straight forward. Topics and Posts, however, are nested resources. They will need a site value that matches the path prefix set by map.resources in Beast.

1
2
3
4
5
6
7
8
9
10
11
12
13
class User < BeastResource
end

class Forum < BeastResource
end

class Topic < BeastResource
  self.site += '/forums/:forum_id'
end

class Post < BeastResource
  self.site += '/forums/:forum_id/topics/:topic_id'
end

That’s all there is to it. Now, let’s play around.

1
2
3
4
5
6
f = Forum.find 1
# notice that since Topic has a prefix, we must pass the forum_id.  
# This is so it can make the request to /forums/1/topics/1.xml
t = Topic.find 1, :forum_id => f.id
p = Post.find 1, :forum_id => f.id, :topic_id => t.id
u = User.find p.user_id

If that all worked, you should be able to experiment with Beast. If you create any posts, please do so in the Testing forum.

1
2
3
4
5
6
7
8
forums = Forum.find :all
testing = forums.detect { |f| f.name == 'Testing' }

# initialize takes two parameters in ActiveResource.  One for the model parameters, and one for the prefix parameters.
topic = Topic.new({
  :title => 'Testing out ARes', 
  :body  => 'Testing 1, 2, 3!'}, 
{ :forum_id => testing.id  })

You may notice a few odd things here. First, #initialize takes a second hash param for the prefix options. This is so it can POST to /forums/5/topics.xml. Also, if you look at the schema for a topic, there is no body attribute. Beast cheats a little bit here and creates both a topic and the first post from one request.

ActiveResource doesn’t know the schema and will basically send whatever you give it. If you’re a little mischievous, you may try making requests to change the posts-count, updated-at, and other “unchangeable” fields. Luckily, Beast protects its attributes with attr_accessible, so this won’t be an issue.

That’s about it for part one of this series. Hopefully you have a little more understanding of where we’re at with ActiveResource, and have had a chance to knock it around a bit. In future articles, I’ll talk about how to customize your Resources for custom applications, how to correctly build API support that ActiveResource can understand, and go into what work remains for ActiveResource. If you want to see how it works from the server side, check out Beast.

Comments

Name:

Email:

Url:


All comments are currently moderated until I figure out a sensible spam solution.