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.

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