Julien Desrosiers

Freelance Web developer.

I’m currently building yet another CMS, this time with Sinatra. And i was having a lot of code duplication in my controllers where i created the usual CRUD (Create Read Update Delete) actions.

Here’s how it works: I have this base class (abridged for this post) for all my controllers, named “Joiedmin”.

class AdminController < Sinatra::Base

  def self.crud(route_prefix, singular_name)

    self.class_eval <<EVAL
      get '#{route_prefix}' do
        @#{singular_name.pluralize} = #{singular_name.pluralize.classify}.all
        haml :index
      end

      get '#{route_prefix}new' do
        @#{singular_name} = #{singular_name.pluralize.classify}.new
        haml :new
      end

      post '#{route_prefix}new' do
        @#{singular_name} = #{singular_name.pluralize.classify}.new(params[:#{singular_name}])
        if @#{singular_name}.save
          redirect '/admin#{route_prefix}#{singular_name.pluralize}'
        else
          haml :new
        end
      end

      get '#{route_prefix}edit/:id' do
        @#{singular_name} = #{singular_name.pluralize.classify}.find params[:id]
        haml :edit
      end

      put '#{route_prefix}edit/:id' do
        @#{singular_name} = #{singular_name.pluralize.classify}.find params[:id]
        if @#{singular_name}.update_attributes(params[:#{singular_name}])
          redirect '/admin#{route_prefix}#{singular_name.pluralize}'
        else
          haml :edit
        end
      end

      delete '#{route_prefix}delete/:id' do
        #{singular_name.pluralize.classify}.find(params[:id]).destroy
        redirect '/admin#{route_prefix}#{singular_name.pluralize}'
      end
EVAL
  end

end

(Note that for the “pluralize” and “classify” methods to work, you’ll need to include “activesupport” in your Gemfile.)

And in each of my controller’s classes, all i have to do is just calling the crud method like so:

class Acclaims < Joiedmin::AdminController
  crud '/', 'acclaim'
  # more controller stuff...    
end

I found the class_eval trick in this thread: http://stackoverflow.com/questions/973728/self-class-eval-def-def.