Overview of make_resourceful 0.1.0
I said last Monday I’d mention when the make_resourceful Rails plugin, which Hampton Catlin, Jeff Hardy, and I have been working on, is released. Well, as of yesterday (the 25th) around midnight, it was. See Hampton’s blog post for the official announcement. The main points are as follows:
- Very alpha release. The API is subject to change, although it probably won’t for the most part.
- There’s a Google group.
- Install with
./script/plugin install http://svn.hamptoncatlin.com/make_resourceful/trunk.
For those who didn’t catch my last post about it and are too lazy to go back and read it, make_resourceful is a plugin that allows you to factor out all the repetitive REST code that clutters up the controller a surprising amount. It manages this by automatically creating typical RESTful actions, while allowing plenty of room for user customization.
actions
The core functionality of make_resourceful comes from the actions method1.
This tells make_resourceful which of the typical RESTful actions
(index, show, new, create, edit, update, and destroy) should be auto-generated. For example:
class VideosController < ApplicationController make_resourceful do actions :index, :show, :new, :create, :destroy end end
It simply takes a list of symbols with the action names, and exposes the proper actions, all ready with their typical operation. If you want to auto-generate all the possible actions, it’s even easier:
class VideosController < ApplicationController make_resourceful do actions :all end end
I’m sure most folks are familiar with the default actions,
but for the sake of those who aren’t
and for specifying exactly what make_resourceful handles,
I’ll go over what each auto-generated action does.
index
index simply loads in a list of relevant objects
and renders the template.
For example, for VideosController,
it would assign the attribute
current_objects and the instance variable @videos to a list of all Videos.
show
show also just loads the relevant object.
For VideosController,
it would assign both current_object and @video
to the video specified by params[:id].
edit
edit works identically to show:
it finds the current object
and loads it into the proper instance variables.
new
new is similar to show,
but instead of finding an object,
it simply creates a new one.
Thus, for VideosController,
current_object and @video would both be assigned to
(the same) newly created Video object.
create
This is where it starts getting tricky. Don’t be frightened, though; the default actions getting tricky means that the tricky stuff is now stuff that’s taken care of for you.
create builds a new instance of the current model
with the parameters passed in
(presumably by a form rendered with new),
then tries to save that instance.
For example, for VideosController,
it would build current_object and @video
with the parameters from params[:video].
If the saving succeeds,
flash[:notice] is set with an appropriate success message
and the user is redirected to the show page for the newly created object.
Otherwise, if it fails,
flash[:error] and an appropriate HTTP error are set,
and the new action is rendered.
Note that in this case the user isn’t actually redirected;
thus, the object that’s made available to new.rhtml
has all the user’s attributes set,
as well as whatever errors caused the save to fail.
update
update is nearly identical to create.
The only difference is that instead of building a brand new object,
it finds the existing one and updates the attributes,
just as you’d expect.
Also, if the update fails, edit is rendered rather than new.
destroy
destroy also works similarly to create.
It finds the relevant object,
then tries to destroy it.
If the object is successfully destroyed,
flash[:notice] is set and
the user is redirected to index.
Otherwise, flash[:error] is set
and the user is redirected back to the page they were previously viewing.
belongs_to
make_resourceful also deals easily with nested resources.
In order to activate this functionality,
you simply have to declare the chain of ancestors
using the belongs_to method.
For example, if each Video had several Scenes
and each Scene in turn has several Frames,
you would declare it as so:
class FramesController < ApplicationController make_resourceful do actions :all belongs_to :video, :scene end end
You’re simply declaring the chain of ancestors, from the topmost (Video) down.
belongs_to does two very useful things.
First, it automatically causes all the parent objects to be assigned.
For example, for FramesController,
@video and @scene would both be assigned before every action.
Second, it ensures that all model searches are properly scoped.
For example, suppose the Frame with id 42 belonged to the Scene with id 3.
The URL “videos/12/scenes/5/frames/42” wouldn’t be valid;
Frame 42 doesn’t belong to Scene 5.
belongs_to ensures that this won’t blithely serve up Frame 42 anyway;
instead, it acts just as though Frame 42 couldn’t be found at all.
The URL “videos/12/scenes/3/frames/42”, on the other hand, will work fine.
before and after
Now, I think I know what you might be thinking. “All this automation is great,” you may cognate, “but what if I want my action to do something special? Do I just give up and define it all myself?”
Not at all, my friend!
make_resourceful provides a vast array of ways for you to customize
your actions to behave in specialized ways.
The simplest way to do so is to use the before and after methods.
These methods take the name of an action and a block to execute,
and then executes the block in the relevant place.
For example2:
before :show do @video.views += 1 end
This shows a few important aspects of before.
It’s not actually the first thing that happens;
the relevant instance variables are loaded beforehand.
The callback order is typically as follows:
- Instance variables are loaded.
beforecallbacks are called.- Business logic is executed.
aftercallbacks are called.- The response is sent out (see
response_for, below).
Note that index, show, new, and edit don’t actually have any business logic2.
Thus, they don’t actually call any after callbacks.
create, update, and destroy, on the other hand,
have plenty of it.
Each of these actually define two after callbacks;
one for when the action succeeds,
and one for when it fails.
For example:
after :create do logger.info "Video #{@video.filename} successfully created!" end after :create_fails do logger.info "Video #{@video.filename} creation failed!" end
A similar pattern applies to update and destroy.
response_for
You may have noticed in my list of the steps in a resourceful action
a step where “the response is sent out.”
This is the step where stuff that the user will see is dealt with,
such as assigning flash notices and errors,
rendering pages,
and redirecting.
Although the default responses for each action are very sensible,
it’s concievable that you might want to change them around for whatever reason.
The response_for method makes this not only possible but easy.
At its most basic, it works just like the other two callbacks.
For example:
response_for :new do render :action => 'edit' end
You can also respond to different formats,
using the same syntax as the built-in respond_to method:
response_for :show do |format| format.html format.json { render :json => @video.to_json } format.xml { render :xml => @video.to_xml } end
A Finer Grain of Control of flash and Redirecting
make_resourceful offers one last bit of power4:
the ability to set the flash message and the redirect
from the client side.
If you post “_flash[notice]” or “_flash[error]” along with form data,
make_resourceful will use those instead of the defaults.
The same goes for “_redirect_on[success]” and “_redirect_on[failure]”.
This gives you a surprising amount of power.
Instead of forcing, say, create to always say “Video created successfully!”,
you can have it say “Video uploaded successfully!” when the user uploads a video,
“Videos merges successfully!” when the user merges two videos into one, etc.
You can similarly control where the user will be redirected to
on what sort of outcome.
All that without adding any extra logic to the controller!
So that’s the plugin in all its present glory!
I can assure you the glory will only increase,
and I’ll be sure to tell all about it when it does.
Until then,
go forth and make_resourceful!
1 This method used to be known as build,
but was changed to actions as that’s more declarative.
2 For simplicity’s sake, I’ll exclude the controller class
and call to make_resourceful for this and future examples.
We’ll say they’re all in VideoController.
3 By “business logic” I mean stuff like saving or deleting models.
4 If you’re super-demanding and want even more cool features, just be patient; they’re in the works.
About Me
Feed
Hamlize Your Site - Without Rails!



Great plugin! REST is the right direction, but already needs a bit of DRYing out. Niiiiiice.
This is a great writeup, Nathan. Thanks for putting it out there.
We are using something very similar at SonicIQ called ‘define_crud’ which can be found here
Documentation is a bit on the poor side at the moment but a glance at the code should explain what’s going on.
Could you add a bit about associate_with. I think I understand it, but wanted to know if there is anything I am missing with it.
Never mind… the Google Group answered that for me!
I’ve added a section on it anyway.
A similar plugin that’s been around for a little while is resources_controller.
I’ve just removed the section on
associate_with, because it was removed frommake_resourceful. Turns out it’s trivially easy to reproduce with a single line of code:before(:create) { current_object.user = current_user }We just didn’t realize quite how much power
make_resourcefulgave us.I have been waiting for someone to come up with something like this. I knew it would happen sooner or later, but seriously you guys have exceeded my expectations quite a bit, this is brilliantly done! I’m off to dry some apps…