RESTful CRUD-Controllers by simulating trivial resource

Hi,

I would like to know your opinion on the following idea:

In order to keep controllers normalized you often have to introdruce new models whose CRUD-actions replace non-CRUD-actions. But sometimes the resulting resources can be nearly trivial. Example: User activation.

=== RPC approach ===

user_controller.rb:

def activate   @user = User.find_by_activiation_ticket(params[:activation_ticket])   @user.update_attributes(:activated => true) end

You *could* refactor this to REST like so:

=== REST approach by introducing new resource ===

- Create model UserActiviation:

user_activation.rb:

class UserActivation < AR   belongs_to :user end

- Create CRUD-Controller UserActivationController.

Downsides: - Database overhead to find out if a user is activated - Seems to be a bit overkill, if you ask me.

Therefor:

=== REST approach by simulating the existance of a resource ===

- *Only* create a UserActivationController

user_activation_controller.rb:

class UserActiviationController < AppController   def create     if params[:user_activation][:user_id]       @user = User.find(params[:user_activiation][:user_id])       @user.update_attributes(:activated => true)     end   end end

That way your api is stricty RESTful. But you do not have to pay the cost of introducing nearly trivial models.

What do you think?

Hi,

REST doesn't imply having to model *everything* to CRUD, hence
support for member functions. An example from my routes ...

  map.resources :subscriptions, :path_prefix => ':locale/ admin', :controller => 'admin/subscriptions', :name_prefix =>
'admin_', :member => { :upgrade => :put, :downgrade => :put} do | subscription>     subscription.resources :payments, :controller => 'admin/ payments', :name_prefix => 'admin_' end

You could implement yours like this ...

Class UsersController.rb < AC::Base

   #CRUD actions here

   def activate      @user = User.find_by_activiation_ticket(params[:activation_ticket])      @user.update_attributes(:activated => true)    end

end

your route:

map.resources :users, :member => { :activate => :put } #post / get if
u like

and invoked with users/1;activate

see http://blog.methodmissing.com/2006/10/30/restful-routes-and- namespaced-controllers , anything's possible with REST and routes,
without having to add additional overhead.

- Lourens

   http://blog.methodmissing.com

Hi,

thanks for your answer. You're right: The original approach does not necessarily conflict with REST and resource orientated routing.

But I still think that there are situations where you might want to provide a strict CRUD-interface for your controllers. For example to allow easy integration with ActiveResource (which does not really allow invocation of actions identified by an ";ascept"-syntax, right?).

Maybe my example was a bit weak, since user activation will not often have to be invoked by webservices. The main idea of my original post was the following: Since REST is all about representations there is no absolute need to introduce a model for every controller. If these "virtual" resources are accessible like all the others from outside, the internal way of storing them does not matter.

And this might be an interesting thing to consider, since some of REST's downsides that I see relate to database issues.

Tim