Howto create a new action with a resource

By the time I’m writing, RESTful applications are in very high position in the top chart of the best software architecture for web applications. So why not to talk about this new way of programming ? :-) In this (small) how to i just want to show you how to add a personalized action inside a scaffolded resource; ok, let’s start!

First of all we need to create a rails application, and then to configure database.yml file to match our database parameters. Once this is done just move inside your application folder and write:

ruby script/generate scaffold_resource message title:string body:string

This simple command will generate a lot of stuff, in detail:

  • A controller named messages_controller
  • A model named message
  • A migration named xxx_create_messages
  • A view folder named message that contains all the scaffold view
  • Fixture and unit tests for the model and the controller

This command also add a line in your ‘config/routes.rb’ file:

map.resources :messages

Ok, now you have a RESTful scaffold, but what if you want to add a new action (for example a ‘read’ flag) ? It’s quite easy: first of all we need a new migration:

ruby script/generate migration read_flag

Now open xxx_read_flag.rb and add:

class ReadFlag< ActiveRecord::Migration

def self.up

add_column :messages, :read, :boolean, :default => false

end

def self.down

remove_column :messages, :read

end

end

Then execute rake db:migrate to synchronize your database with the current migration.

Ok, these steps are not so different from the old-school way of coding, but the following will be. We’re going to map our new action inside our resource, Rails let us choose which HTTP method we want to bind with our action; one of the REST guidelines tell us that we have to map INSERT actions with a HTTP POST method, and UPDATE with PUT, so we have to add to routes.rb:

map.resources :messages, :member => { :read => :post }

Ok, we have just set up a new url: ’/message/n;read’ where n is for the message id, now the most is done, the next steps involve the creation of a read action inside the message controller and the creation of a link (with method post) inside our list view that point to that action.

# Part 1: define the action (inside messages_controller.rb)

def read

respond_to do |format|

if Message.find(params[:id]).update_attribute(:read, true)

format.html { redirect_to message_path }

format.xml { head :o k }

else

format.html { redirect_to message_path }

format.xml { head 500 }

end

end

end

# Part 2: link the action inside our list view (inside/app/views/messages/index.rhtml)

<td><%= link_to ‘Show’, message_path(message) %></td>

<td><%= link_to ‘Edit’, edit_message_path(message) %></td>

<td><%= link_to ‘Destroy’, message_path(message), :confirm => ‘Are you sure?’, :method => :delete %></td>

<td><%= link_to ‘Set the read flag’, read_message_path(message), :method => :post %></td>

And with these last steps we have added our read action keeping the REST model valid. If you need more informations about REST architecture i suggest you to read this pdf: RESTful Rails Development freely avaiable at b-simple-de.

Leave a Comment

*