require 'trusty_cms/resource_responses' class Admin::ResourceController < ApplicationController extend TrustyCms::ResourceResponses helper_method :model, :current_object, :models, :current_objects, :model_symbol, :plural_model_symbol, :model_class, :model_name, :plural_model_name before_filter :populate_format before_filter :never_cache before_filter :load_models, :only => :index before_filter :load_model, :only => [:new, :create, :edit, :update, :remove, :destroy] after_filter :clear_model_cache, :only => [:create, :update, :destroy] cattr_reader :paginated cattr_accessor :default_per_page, :will_paginate_options create_responses do |r| # Equivalent respond_to block for :plural responses: # respond_to do |wants| # wants.xml { render :xml => models } # wants.json { render :json => models } # wants.any # end r.plural.publish(:xml, :json) { render format_symbol => models } r.singular.publish(:xml, :json) { render format_symbol => model } r.singular.default { redirect_to edit_model_path if action_name == "show" } r.not_found.publish(:xml, :json) { head :not_found } r.not_found.default { announce_not_found; redirect_to :action => "index" } r.invalid.publish(:xml, :json) { render format_symbol => model.errors, :status => :unprocessable_entity } r.invalid.default { announce_validation_errors; render :action => template_name } r.stale.publish(:xml, :json) { head :conflict } r.stale.default { announce_update_conflict; render :action => template_name } r.create.publish(:xml, :json) { render format_symbol => model, :status => :created, :location => url_for(:format => format_symbol, :id => model) } r.create.default { redirect_to continue_url(params) } r.update.publish(:xml, :json) { head :ok } r.update.default { redirect_to continue_url(params) } r.destroy.publish(:xml, :json) { head :deleted } r.destroy.default { redirect_to continue_url(params) } end def index response_for :plural end [:show, :new, :edit, :remove].each do |action| class_eval %{ def #{action} # def show response_for :singular # response_for :singular end # end }, __FILE__, __LINE__ end [:create, :update].each do |action| class_eval %{ def #{action} # def create model.update_attributes!(params[model_symbol]) # model.update_attributes!(params[model_symbol]) response_for :#{action} # response_for :create end # end }, __FILE__, __LINE__ end def destroy model.destroy response_for :destroy end def self.model_class(model_class = nil) @model_class ||= (model_class || self.controller_name).to_s.singularize.camelize.constantize end # call paginate_models to declare that will_paginate should be used in the index view # options specified here are accessible in the view by calling will_paginate_options # eg. # # Class MyController < Admin::ResourceController # paginate_models :per_page => 100 def self.paginate_models(options={}) @@paginated = true @@will_paginate_options = options.slice(:class, :previous_label, :next_label, :inner_window, :outer_window, :separator, :container).merge(:param_name => :p) @@default_per_page = options[:per_page] end # returns a hash of options that can be passed to will_paginate # the @pagination_for@ helper method calls @will_paginate_options@ unless other options are supplied. # # pagination_for(@events) def will_paginate_options self.class.will_paginate_options || {} end helper_method :will_paginate_options # a convenience method that returns true if paginate_models has been called on this controller class # and can be used to make display decisions in controller and view def paginated? self.class.paginated == true && params[:pp] != 'all' end helper_method :paginated? # return a hash of page and per_page that can be used to build a will_paginate collection # the per_page figure can be set in several ways: # request parameter > declared by paginate_models > default set in config entry @admin.pagination.per_page@ > overall default of 50 def pagination_parameters pp = params[:pp] || TrustyCms.config['admin.pagination.per_page'] pp = (self.class.default_per_page || 50) if pp.blank? { :page => (params[:p] || 1).to_i, :per_page => pp.to_i } end protected def rescue_action(exception) case exception when ActiveRecord::RecordInvalid response_for :invalid when ActiveRecord::StaleObjectError response_for :stale when ActiveRecord::RecordNotFound response_for :not_found else super end end def model_class self.class.model_class end def model instance_variable_get("@#{model_symbol}") || load_model end alias :current_object :model def model=(object) instance_variable_set("@#{model_symbol}", object) end def load_model self.model = if params[:id] model_class.find(params[:id]) else model_class.new() end end def models instance_variable_get("@#{plural_model_symbol}") || load_models end alias :current_objects :models def models=(objects) instance_variable_set("@#{plural_model_symbol}", objects) end def load_models self.models = paginated? ? model_class.paginate(pagination_parameters) : model_class.all end def model_name model_class.name end def plural_model_name model_name.pluralize end alias :models_name :plural_model_name def model_symbol model_name.underscore.intern end def plural_model_symbol model_name.pluralize.underscore.intern end alias :models_symbol :plural_model_symbol def humanized_model_name t(model_name.underscore.downcase) end def continue_url(options) options[:redirect_to] || (params[:continue] ? {:action => 'edit', :id => model.id} : index_page_for_model) end def index_page_for_model parts = {:action => "index"} if paginated? && model && i = model_class.all.index(model) p = (i / pagination_parameters[:per_page].to_i) + 1 parts[:p] = p if p && p > 1 end parts end def edit_model_path method = "edit_admin_#{model_name.underscore}_path" send method.to_sym, params[:id] end def announce_validation_errors flash.now[:error] = t("resource_controller.validation_errors") end def announce_removed ActiveSupport::Deprecation.warn("announce_removed is no longer encouraged in TrustyCms 0.9.x.", caller) flash[:notice] = t("resource_controller.removed", :humanized_model_name => humanized_model_name) end def announce_not_found flash[:notice] = t("resource_controller.not_found", :humanized_model_name => humanized_model_name) end def announce_update_conflict flash.now[:error] = t("resource_controller.update_conflict", :humanized_model_name => humanized_model_name) end def clear_model_cache Rails.cache.clear end def format_symbol format.to_sym end def format params[:format] || 'html' end # I would like to set this to expires_in(1.minute, :private => true) to allow for more fluid navigation # but the annoyance for concurrent authors would be too great. def never_cache expires_now end # Assist with user agents that cause improper content-negotiation # warn "Remove default HTML format, Accept header no longer used. (#{__FILE__}: #{__LINE__})" if Rails.version !~ /^2\.1/ def populate_format params[:format] ||= 'html' unless request.xhr? end end