Rails enables web services by default, which is pretty awesome, and I’ve been relying on that for a while. It is pretty nifty how Rails will magically parse XML post parameters, create an in-memory object and then save that object to the database without your having to write one line of code. However, when the magic fails it can be pretty hard to debug. I found it useful to run basic tests on the command line using curl (hearing the voice of Zach Moazeni in my head saying: “test your assumptions.”)

Below is a writeup of the set of curl commands and sample output for testing the default Rails XML REST APIs. This can serve as a cheat sheet for the experienced or an introduction for folks new to rails who want a basic understanding of the default webservice APIs.

Create an app, by typing the following commands into your terminal:

$ rails basic_app
$ cd basic_app
$ ./script/generate scaffold project title:string description:text
$ rake db:migrate
$ ./script/server

In Rails 2.3, you also need to added the following line to the top of app/controllers/projects_controller.rb (This will allow external access to the APIs.) You can make this change while the server is running, btw.

skip_before_filter :verify_authenticity_token

Leave that window open where you can see it, since it will output useful stuff from the log. Then in another terminal window, experiment with the following commands to interact with your application APIs.

blockquote.code {
font-style: normal;
font-family: Monaco,monospace;
font-size: 12px;
border: solid 1px #aaa;
padding: 6px;
background-color: #eee;
color: inherit;
margin: 10px 0px;


POST /projects.xml

Create a project object based on the XML representation given in the post body and save in the projects database table.

$ curl -X POST -d "<project><title>Awesome</title><description>This is an awesome project.</description></project>" -H "Content-Type: application/xml" http://localhost:3000/projects.xml

<?xml version="1.0" encoding="UTF-8"?>
  <created-at type="datetime">2009-06-21T10:13:43-07:00</created-at>
  <description>This is an awesome project.</description>
  <id type="integer">6</id>
  <updated-at type="datetime">2009-06-21T10:13:43-07:00</updated-at>


GET /projects.xml

This returns a list of all of the projects in the database with an automatically generated XML representation.

$ curl http://localhost:3000/projects.xml<?xml version="1.0" encoding="UTF-8"?>

<projects type="array">
  <created-at type="datetime">2009-06-21T10:13:19-07:00</created-at>
  <description>This is an awesome project.</description>
  <id type="integer">1</id>
  <updated-at type="datetime">2009-06-21T10:13:19-07:00</updated-at>
  <created-at type="datetime">2009-06-21T10:13:43-07:00</created-at>
  <description>New information here</description>
  <id type="integer">2</id>
  <updated-at type="datetime">2009-06-21T10:49:21-07:00</updated-at>


GET /projects/1.xml

This returns an xml representation of the project with id #1

$ curl http://localhost:3000/projects/1.xml<?xml version="1.0" encoding="UTF-8"?>

  <created-at type="datetime">2009-06-21T10:45:19-07:00</created-at>
  <description>This is an awesome project.</description>
  <id type="integer">8</id>
  <updated-at type="datetime">2009-06-21T10:45:19-07:00</updated-at>


PUT /projects/1.xml

This modifies the project with id #1

curl -X PUT -d "<project><description>New information here</description></project>" -H "Content-Type: application/xml" http://localhost:3000/projects/1.xml

RSpec for View Helpers

  • To test a view helper, you need to test the plugin in the context of a rails app
  • To verify that you can put the following code into your spec_helper.rb (or just use rspec-plugin-generator by Pat Maddox which will generate this code for you)
      require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
    rescue LoadError
      puts "You need to install rspec in your base app"
  • By convention, helper examples live in spec/helpers/ then their dependencies will get magically included.   David Chelimsky notes

    All directories under spec/ are potentially magic – rspec will always
    look at spec/:directory/:filename and see if it has an example group
    type registered for whatever directory is. So if there *is* a foo
    example group type, it will be used for any spec file in spec/foos

  • If you put helpers elsewhere, then you need to declare their type (or manually include dependencies)
    describe AppletHelper, :type => :helper do
  • To send params in your test, you can just define them before calling your view helper.  For example:
    describe DogHelper do
      it "should bark" do
        params[:debug] = "foo"
        html = helper.bark
        html.should have_tag("script")

What do you do when some behavior depends on RAILS_ENV?

  • It’s not a good practice to switch around RAILS_ENV in the test framework
  • Better idea is use a method to check it and then stub that out
  • Here’s an outline:  gist from Zach
  • Here’s what I did: EnvChecker, code and example

Stub tip

If you stub something and it appears not to be working, check when your module, class or method is loaded or created.  Dynamic languages can be challenging.  (thanks David)


For more information, see

These lessons learned while developing RSpec examples for a bug fix in openlaszlo_plugin with help from Zach Moazeni, RailsBridge mentor, and David Chelmsky, on the RSpec forum.

Sometimes it takes quite an effort to be a “lazy programmer” (as in Larry Wall’s virtues of a programmer). I’ve been trying to optimize my workflow as I run into things that make for repetitive typing. I find when I can type less, I have more cycles to think. One of my favorite tools in laziness is bash scripting, but I’m still learning its ins and outs.

The problem: Lately I’ve been switching between subversion trees in OpenLaszlo. (Someday I want to convince the team to switch to git, but I’m not sure that would even solve the problem completely, since I also like having multiple webapps installed.) So I’ve got trunk checked out in different directories: a clean one for testing, one I keep for code reviews, a sandbox for whatever I’m working on at the moment, etc. Every time I switch OpenLaszlo contexts, I need to redefine $LPS_HOME environment variable and cd into that directory. Should be simple, huh?

[ -n "$1" ] && BRANCH="$BRANCH-$1"


export LPS_HOME=/Users/sarah/src/svn/openlaszlo/$BRANCH
cd "/Users/sarah/src/svn/openlaszlo/$BRANCH"

Except this didn’t work. It seemed that ‘cd’ had no effect and $LPS_HOME wasn’t modified. WTF? Lacking someone to look over my shoulder in my new solo work situation, I emailed my friend Scott Evans from whom I have learned much bash lore. He emailed me the following:

1) use “.” to run the script, which runs it in your shell process instead
of in a child one.

2) use a bash function instead — these run in your current environment.
try something like this in your bashrc/bash_profile:

trunk() {
 echo "dollar 1: ${1}"
 if [ -n "${1}" ] ; then
   export LPS_HOME=/Users/sarah/src/svn/openlaszlo/trunk-${1}
   export LPS_HOME=/Users/sarah/src/svn/openlaszlo/trunk


Note that I didn’t set something like $TRUNK there — since the thing is running in your shell environment, it’s good practice not to potentially step on existing variables, or leave any variables defined after the fact.

Thanks Scott! Posting here so that I will always remember what I learned today and maybe some other folk will find it helpful.