Created
November 30, 2011 21:23
-
-
Save hopsoft/1410915 to your computer and use it in GitHub Desktop.
Resourceful Rails actions for free with a Sinatra like DSL for action callbacks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Resourceful | |
def self.actions | |
[:index, :show, :new, :edit, :create, :update, :destroy] | |
end | |
def self.callbacks | |
[:before, :after, :respond_to] | |
end | |
module ControllerClassMethods | |
def set_resourceful_model(arg) | |
@resourceful_model = arg | |
end | |
alias :resourceful_model= :set_resourceful_model | |
def resourceful_model | |
return @resourceful_model if @resourceful_model | |
# try to determine the model based on convention | |
name = self.name.gsub(/Controller$/i, "").classify | |
# require the file to ensure the constant will be defined | |
require "#{RAILS_ROOT}/app/models/#{name.underscore}" rescue nil | |
@resourceful_model = Object.const_get(name) | |
end | |
def resourceful_callbacks | |
@resourceful_callbacks ||= HashWithIndifferentAccess.new | |
end | |
# define callback setters | |
Resourceful.callbacks.each do |callback| | |
Resourceful.actions.each do |action| | |
eval <<-DEF | |
def #{callback}_#{action}(value=nil, &block) | |
callback = value if value | |
if block_given? | |
define_method(:#{callback}_#{action}, block) | |
callback = :#{callback}_#{action} | |
end | |
resourceful_callbacks[:#{callback}_#{action}] = callback | |
end | |
DEF | |
end | |
end | |
end | |
# extend the controller class definition | |
def self.included(controller) | |
controller.extend(ControllerClassMethods) | |
end | |
# ----------------------------------------------------------------------------------------------- | |
# begin restful actions | |
def index | |
invoke_callback(:before, :index) | |
@resourceful_list ||= resourceful_model.all | |
init_instance_variables | |
invoke_callback(:respond_to, :index) | |
unless performed? | |
respond_to do |format| | |
format.html # index.html.erb | |
format.xml { render :xml => @resourceful_list } | |
format.js { render :json => @resourceful_list } | |
end | |
end | |
invoke_callback(:after, :index) | |
end | |
def show | |
invoke_callback(:before, :show) | |
@resourceful_item ||= resourceful_model.find(params[:id]) | |
init_instance_variables | |
invoke_callback(:respond_to, :show) | |
unless performed? | |
respond_to do |format| | |
format.html # show.html.erb | |
format.xml { render :xml => @resourceful_item } | |
format.js { render :json => @resourceful_item } | |
end | |
end | |
invoke_callback(:after, :show) | |
end | |
def new | |
invoke_callback(:before, :new) | |
@resourceful_item ||= resourceful_model.new | |
init_instance_variables | |
invoke_callback(:respond_to, :new) | |
unless performed? | |
respond_to do |format| | |
format.html # new.html.erb | |
format.xml { render :xml => @resourceful_item } | |
format.js { render :json => @resourceful_item } | |
end | |
end | |
invoke_callback(:after, :new) | |
end | |
def edit | |
invoke_callback(:before, :edit) | |
@resourceful_item ||= resourceful_model.find(params[:id]) | |
init_instance_variables | |
invoke_callback(:respond_to, :edit) | |
invoke_callback(:after, :edit) | |
end | |
def create | |
invoke_callback(:before, :create) | |
@resourceful_item ||= resourceful_model.new(params[resourceful_model.name.underscore]) | |
init_instance_variables | |
success = @resourceful_item.save | |
invoke_callback(:respond_to, :create) | |
unless performed? | |
respond_to do |format| | |
if success | |
flash[:notice] = "#{resourceful_model.name} was successfully created." | |
format.html { redirect_to(@resourceful_item) } | |
format.xml { render :xml => @resourceful_item, :status => :created, :location => @resourceful_item } | |
format.js { render :json => @resourceful_item, :status => :created, :location => @resourceful_item } | |
else | |
format.html { render :action => "new" } | |
format.xml { render :xml => @resourceful_item.errors, :status => :unprocessable_entity } | |
format.js { render :json => @resourceful_item.errors, :status => :unprocessable_entity } | |
end | |
end | |
end | |
invoke_callback(:after, :create) | |
end | |
def update | |
invoke_callback(:before, :update) | |
@resourceful_item ||= resourceful_model.find(params[:id]) | |
init_instance_variables | |
success = @resourceful_item.update_attributes(params[resourceful_model.name.underscore]) | |
invoke_callback(:respond_to, :update) | |
unless performed? | |
respond_to do |format| | |
if success | |
flash[:notice] = "#{resourceful_model.name} was successfully updated." | |
format.html { redirect_to(@resourceful_item) } | |
format.xml { head :ok } | |
format.js { head :ok } | |
else | |
format.html { render :action => "edit" } | |
format.xml { render :xml => @resourceful_item.errors, :status => :unprocessable_entity } | |
format.js { render :json => @resourceful_item.errors, :status => :unprocessable_entity } | |
end | |
end | |
end | |
invoke_callback(:after, :update) | |
end | |
def destroy | |
invoke_callback(:before, :destroy) | |
@resourceful_item ||= resourceful_model.find(params[:id]) | |
init_instance_variables | |
@resourceful_item.destroy | |
invoke_callback(:respond_to, :destroy) | |
unless performed? | |
respond_to do |format| | |
format.html { redirect_to(send("#{resourceful_model.table_name}_url")) } | |
format.xml { head :ok } | |
format.js { head :ok } | |
end | |
end | |
invoke_callback(:after, :destroy) | |
end | |
# end restful actions | |
# ----------------------------------------------------------------------------------------------- | |
protected | |
def resourceful_model | |
self.class.resourceful_model | |
end | |
def resourceful_callbacks | |
self.class.resourceful_callbacks | |
end | |
def init_instance_variables | |
item_name = resourceful_model.name.underscore | |
eval "@#{item_name} ||= @resourceful_item" | |
eval "@#{item_name.pluralize} ||= @resourceful_list" | |
end | |
private | |
def invoke_callback(callback, action) | |
method = resourceful_callbacks["#{callback}_#{action}"] | |
send(method) if method.is_a?(Symbol) || method.is_a?(String) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment