One question I’m still puzzling through with Ruby on Rails is the logical unit of reuse for Web actions. This is a key question regardless of which Web application platform you use.

Since everybody has been exposed to PHP, let me use it to explain what I’m talking about. Let’s say you’re writing an application that enables a user to manage a weblog. Obviously, there’s going to be some shared code that you put in include files, but what I’m talking about is the top level interface to the Web site, the URLs. You could have one URL, index.php, and then put all of the verbs for your site in parameters, so you’d have URLs like:

  • /index.php?action=post
  • /index.php?action=view&id=50
  • /index.php?action=configure&weblog=5
  • /index.php?action=configureauthors&weblog=5

To be blunt, that’s an approach I hate. I prefer one page per verb. So if I were writing a weblog application, I’d have URLs more like this:

  • /post.php
  • /view.php?id=50
  • /config/index.php?weblog=5
  • /config/authors.php?weblog=5

One area where I generally do go for reuse of the same page is in processing form submissions, so rather than having two pages like post.php and save_post.php, I just write one page that displays a new form when it’s supposed to and processes the form submission when it’s supposed to.

This isn’t the sort of thing where there’s one right answer, it’s a matter of aesthetics and ease of maintenance. Right now I’m trying to figure out the right mix for Ruby on Rails. In Ruby on Rails, there are scripts called controllers that are basically packages of actions (or verbs, if you prefer). Public methods in the controller are the verbs, and correspond to the URLs, by default anyway.

So in Rails, you have mappings like this:

URLcontrollermethod
/blog/post blog_controller.rb post
/admin/new_blog admin_controller.rb new_blog
/blog/update/503 blog_controller.rb update

In the last example, Rails is smart enough to pass in 503 to the method as the parameter “id”. This behavior makes it easy to write shorter, cleaner URLs.

My general rule when it comes to Rails is to treat the controllers as nouns and the method names as verbs, so my examples there aren’t the best. For a weblog tool, I might have controllers like “blog” and “post”, and then the methods would be verbs that apply to those nouns. In one of my current Rails packages, though, one of my controllers is getting unwieldy, so I think I’m going to split it up into multiple controllers.

I follow the same rule as I do with PHP with Ruby on Rails. I don’t reuse methods in controllers for different tasks, even if they do basically the same thing. (That’s where I get the “units of reuse” I mention in the title of the item.) Say, for example, I have some search functionality in my application, at the URL /posts/search. Later on, I decide that I can use search to prevent users from entering a post with the same URL as an earlier post. I could just use a parameter to include my existing search method in the process, like this:

/post/search?step=checkforduplicates

Then in my search method I would check the step parameter to determine whether to show search results or show the “check for duplicates” page when finished. This is not how I would write an application. Instead I would create an entirely new check_for_duplicates method, and then extract the common code from the search method so that it could be used by both of my top level methods. To me, that’s a cleaner approach, and makes for nicer URLs in the application.

The reason I bring all of this up is that when you’re working on a team, this is the sort of thing you have to hash out and agree on among all team members for an application to be written in a sensible and consistent fashion. If one person is writing one method to display the “new post” form and another save new posts, and another person is wrapping them all into one method and keying off of the request method to determine which action to take when the method is called, you wind up with an application that’s difficult to maintain.

At work, I’m in the process of coming up with just these sorts of guidelines for our Ruby on Rails projects.