My Profile page: a RESTful single resource using Formtastic

I’ve just implemented the My Profile tab for Sano:


Can I write 500 words about? Well, I can try.

I like using RESTful routes. In case you don’t know what they are let me try to explain it quick, at least the relevant part. You normally have a set of route rules that would point /movies to the movie listing, /movies/new to a form to add a new movie, /movies/123 to see the movie 123. With RESTful routes in Rails all that is done automatic in a single line:

map.resources :movies

What you are doing is defining a resource. The resource has several actions that can be performed on them:

  • index (a.k.a.: listing)
  • new
  • edit
  • create
  • update
  • destroy

In Sano I have a weights resource that is a very fine example of it:

map.resources :weights

Running the rake routes command we can see all the routes it generate:

    weights GET    /weights(.:format)          {:action=>"index", :controller=>"weights"}
            POST   /weights(.:format)          {:action=>"create", :controller=>"weights"}
 new_weight GET    /weights/new(.:format)      {:action=>"new", :controller=>"weights"}
edit_weight GET    /weights/:id/edit(.:format) {:action=>"edit", :controller=>"weights"}
     weight GET    /weights/:id(.:format)      {:action=>"show", :controller=>"weights"}
            PUT    /weights/:id(.:format)      {:action=>"update", :controller=>"weights"}
            DELETE /weights/:id(.:format)      {:action=>"destroy", :controller=>"weights"}

You see the (.:format) in there? That means that every route is also accessible in alternative formats. For example: xml. Go and try it, add some weights and access

If you are curious, the code for that is this:

def index
  @weights = user.weights.all

  respond_to do |format|
    format.xml  { render :xml => @weights }

I now want everything to be a resource. How can “my profile” be a resource? Well, it’s not hard. It’s not a collection resource, it’s a single resource. There’s no list of profiles, no creation of new profiles or destruction of profiles. There’s only editing and updating of a single profile (which is actually your user).

It turns out that in Rails, that’s very easy to define:

map.resource :profile, :only => [:edit, :update]

Notice how it says “resource” instead of “resources” and it only allows certain actions. Rails is really quite flexible here, logging in is also a resource. It’s called session and you can create them, by logging in, or destroy them, by logging out (no editing). There’s also an extra action needed by OpenID. This is the route definition:

map.resource :session, :only => [:new, :create, :destroy], :member => { :finish_creating => :get }

The “member” part specifies that action to be only for items, not for the whole collection. If it was a collection resource, you could have extra listings. The same way you have index, you could have sorted_index.

The form in the my-profile-page is an example of what Formtastic is good at. This is the whole form:

<% semantic_form_for @user, :url => profile_url do |f| %>
  <% f.inputs do -%>
    <%= f.input :name %>
    <%= f.input :email %>
    <%= f.input :height, :hint => "meters" %>
    <%= f.input :gender, :as => :radio, :collection => [["Male", false], ["Female", true]] %>
    <%= f.input :birthday, :start_year => 1900, :end_year => %>
  <% end -%>
  <% f.buttons do -%>
   <%= f.commit_button :label => "Update profile" %>
  <% end -%>
<% end %>

Special thanks to Ryan Bates who covered the gender case in Railscasts episode 184 and Eifion Bedford of ASCIIcasts for making it easy to find. It surely would have take me some time to figure it out.

Can you please update your profile on Sano?

There you go 553 words!

ReStructured Text on WordPress

I am coming from the Plone world. My web site used to be Plone and various website I still maintain are still Plone-based. In Plone, one of the formats to write text is ReStructured Text (RST); and Matt has convinced me it is the right way… or at least, one good way. But in the world of WordPress, RST is not a first class citizen.

Searching for “restructured text wordpress” I’ve found an article titled “Using reStructuredText with WordPress” . That seemed like good news. The author talks about a plug in, but getting it to work required some work on my side and that is what I am trying to show here.

Disclaimer: poorly written article ahead (and above), take the information, ignore the prose.

First, the plug in is not distributed as a compressed archive (tar.gz, tar.bz2, etc) like software is generally distributed but as a TXT. You have to download rest.php-1.2.txt to your plugins directory of your WordPress install and rename it to “rest.php”.

In the computer were WordPress is installed you should also have Docutils installed, particularly the program rst2html. The plug in has a hard-codded path to reach that program, around line 18:

// Set this to the prefix of your docutils installation.
$prefix = "/usr/local";

// Set this to the path of
$rst2html = "$prefix/bin/";

since I am running Debian GNU/Linux and installed Docutils using the package, the binary was in /usr/bin/ so I have to change the prefix to be:

// Set this to the prefix of your docutils installation.
$prefix = "/usr/local";

Also, due to various personal preferences, I’ve changed the line 116 to:

$execstr = $rst2html . ' --no-generator --no-source-link --rfc-references --no-doc-title --initial-header-level=2 --footnote-references="superscript"';

To know more about it, read the man page of rst2html.

The other important change is that around line 100, there’s some code to replace the “more” HTML links that WordPress insert with RST links. The problem with that is that the code searches for a particular text (“(more…)”):

$pattern = '\(more...\)';
$replacement = "\n\n`(more...) < \1>`__\n\n";
$text = ereg_replace($pattern, $replacement, $text);

but that text is skin-dependent, so I changed it for:

$pattern = '(.*)';
$replacement = "\n\n`\2 < \1>`__\n\n";
$text = ereg_replace($pattern, $replacement, $text);

which is more generic and will successfully correct all the links, no matter what they say. Now that I take a look at it, the line jumps in the RST version shouldn’t be there. This had an unfortunate consequent. The text of the a element of an HTML link can have HTML specific stuff, in my case it had one HTML entity. The right thing would be to expand all HTML entities into text, but I just did a search and replace for this particular one. An ugly hack indeed:

$pattern = '»';
$replacement = "»";
$text = ereg_replace($pattern, $replacement, $text);

And at last the jewel. If you don’t write -*- mode: rst -*- somewhere in the article, then it won’t be RST, it would be the built-in simple WordPress markup language whatever that is called. You can prefix that with two dots and a space, like “.. “, in the beginning of the line to also turn it into a RST comment so the actual text doesn’t appear in the final article.

You’ll see that there are many nasty things here, lots of hacks, etc. The right thing would have been to solve the bugs, make a customization page to set the path and the RST options and make the solution more generic. Then pack it and release it. I am not going to do that, enough time has been spent writting it down here, now I am back to my main project. This is related to what I’ve said in my previous post regarding worrying less about the perfectionism of my web site and work more in my personal projects.


Comments in the original post

  1. Matt Dorn Says:
    Finally caught up with your new site and updated my RSS feeds–looks nice! But I like that I can now read your entire articles within my RSS reader instead of just the introduction.I agree that Plone is not ideal for a personal site, though I think I’ll be keeping mine for a while. I would like to get comments activated without hosing my Apache caching setup–that seems to be the main challenge, because running a Plone site without caching is not advisable.

    Re. our shared enthuasiasm for Restructured Text, I just had another occasion to appreciate it. You can use it in Tracs. I also got Tracs working with Darcs, which I know you use as well. Have you thought about making your software projects available via Tracs projects? If so, the writeup I just did might help you:

    February 1st, 2007 at 13:01

  2. Pupeno Says:

    Hello Matt,

    Nice to see you active in the community. When I was re-structuring my web site I’ve decided to use Trac for my projects but after a quick try I gave up. A quick try to use it with Darcs (or nothing at all) that is.

    Now that you have written a tutorial about it I am going to read it and give it a nice try. Isn’t it nice that I helped you start with darcs and now you help me start with trac plus darcs? That’s karma!

    February 1st, 2007 at 20:40 e

  3. Ivan Says:

    Dear Pupeno,

    I’ve just installed this plugin to a blog on my local machine (not the blog above). It doesn’t quite work. If I could get it working it would be an absolute godsend. Please help.

    When I add the mode line to a post, wordpress then ignores the entire body of the post – I get the title and nothing else. Any idea what might be wrong?

    I have no knowledge of php at all, my main language is Python. Would it be possible to write plugins in Python?

    My blog is fairly new. I’m enjoying using wordpress, but the rest of the time I more or less live in emacs and use rest for most of my documentation. If I could write my blog posts in rest I should be very happy. Would be prepared to put some work into this to get it working.

    Best wishes


    June 15th, 2007 at 12:52 e

  4. Pupeno Says:
    Hello Ivan,Be sure that the plug in is activated. Otherwise, contact the plug in author.

    I am not sure about programming plug ins in Python but I doubt it’ll be possible, you should check in WordPress’ site and mailing lists.

    I am only a user of WordPress, my knowledge of its internals is null, but if you ask in WordPress’ mailing list or IRC channels, I am sure you’ll get a lot of help.

    June 16th, 2007 at 13:53 e

  5. you know something? » Blog Archive » Happy! ReST Says:
    […] 落ち着いて考えれば、すぐ分かりそうなものですが、 以前、うまくいかなかった理由は、 をあらかじめインストールしておいて、 rest.php 内のパス を書き換えておかったため。 […]September 7th, 2007 at 2:41 e
  6. ROTR » reStructuredText for WordPress is now a Launchpad project Says:
    […] Pupeno […]September 9th, 2007 at 5:30 e