Rails and Nested Singular Resources

One of the reasons I love Rails is the built in support for REST. If you're not yet writing your Rails applications RESTfully, then you're not really writing web applications.

I'll detail an example that I just created which I thought illustrated REST support quite nicely. In Rails, you can model singular or plural Resources. A plural Resource might be Users, which means you'll have lots of Users in your system. In contrast, you can create singular Resources when there is only one instance of that Resource in the system.

A good example of a singular resource is an User's avatar icon. For instance, most Web 2.0 applications let you upload a tiny picture that represents you. In Rails speak, we say a User has one Avatar Icon. An Avatar Icon belongs to a User.

When creating the URI space for these models (User, AvatarIcon) you use map.resources and map.resource inside of your routes.rb file. We want to enforce that an AvatarIcon belongs to an User in the URI space, and thus the modeling of the Resource. We can do that with the below routes:



map.resources :users do |user|
user.resource :avatar_icon
end



Our URIs will look like this now:


  • /users - list all users

  • /users/1 - show a single user

  • /users/1/avatar_icon - a user's avatar icon



You can see the difference between singular and plural even in the URIs. /users is plural to indicate that it identifies the collection of all users in the system. On the other hand, /users/1/avatar_icon is singular indicating that it identifies the single avatar icon for a single user.

Furthermore, when you use map.resources, Rails will create named routes for you. This makes referring to the URIs for the Resources much easier, as they are given logical, proper names. Now, here's where I think it gets really cool. Refer to the routes example above, where we nested the avatar_icon resource inside the users resource. When we want to create the URI /users/1/avatar_icon, we can use the generated named route avatar_icon_path(@user).

Notice how we only need to specify the user in question when building the URI to a user's avatar icon. There's no ID for the avatar icon in the URI, so why specify that in the named route? When I saw that, I said, "Yes, that's exactly how I would expect it to work."

Way to go, Rails! Making RESTful development a first class citizen for web applications.

Popular posts from this blog

Lists and arrays in Dart

Converting Array to List in Scala

Null-aware operators in Dart