diff --git a/init.rb b/init.rb index 00e9bb8..c3b9b59 100644 --- a/init.rb +++ b/init.rb @@ -1,5 +1,11 @@ require 'sortable_columns' require 'helpers/view_helpers' +require 'helpers/active_record_base_methods' ActionController::Base.send(:include, SortableColumns) -ActionView::Base.send(:include, SortableColumns::ViewHelpers) \ No newline at end of file +# allow sort_params to preserve existing params +# (minus standard params like :controller, :action, etc ) +ApplicationController.send( :append_before_filter, :store_params) + +ActionView::Base.send(:include, SortableColumns::ViewHelpers) +ActiveRecord::Base.send(:extend, SortableColumns::ActiveRecordBaseMethods) \ No newline at end of file diff --git a/lib/helpers/active_record_base_methods.rb b/lib/helpers/active_record_base_methods.rb new file mode 100644 index 0000000..8b48ac1 --- /dev/null +++ b/lib/helpers/active_record_base_methods.rb @@ -0,0 +1,10 @@ +module SortableColumns + + module ActiveRecordBaseMethods + attr_accessor :sortable_methods + + def sortable_instance_methods(methods) + @sortable_methods = methods.to_a + end + end +end \ No newline at end of file diff --git a/lib/helpers/view_helpers.rb b/lib/helpers/view_helpers.rb index 4fa126b..79a9c7c 100644 --- a/lib/helpers/view_helpers.rb +++ b/lib/helpers/view_helpers.rb @@ -3,21 +3,19 @@ module SortableColumns module ViewHelpers def sort_params(sortable, column) - raise ParameterError.new("Please provide a Class as your first param. Ex: sort_param(User, :created_at)") unless sortable.is_a?(Class) - raise ParameterError.new("#{sortable} has no column \"#{column}\".") unless sortable.column_names.include?(column.to_s) - + SortableColumns.validate_params(sortable, :sort_by=>column) init_session unless session[:sortable_columns] if session[:sortable_columns][sortable.to_s.downcase.to_sym] if session[:sortable_columns][sortable.to_s.downcase.to_sym][column.to_sym] == "asc" - return { :sort_by => column.to_s, :order => 'desc' } + return params.merge( { :sort_by => column.to_s, :order => 'desc' } ) else - return { :sort_by => column.to_s, :order => 'asc' } + return params.merge( { :sort_by => column.to_s, :order => 'asc' } ) end end # default - return { :sort_by => column.to_s, :order => 'desc' } + return params.merge( { :sort_by => column.to_s, :order => 'desc' } ) end private diff --git a/lib/sortable_columns.rb b/lib/sortable_columns.rb index 53e9e5f..43a1bb4 100644 --- a/lib/sortable_columns.rb +++ b/lib/sortable_columns.rb @@ -4,9 +4,9 @@ class ParameterError < StandardError; end def sortable_order(sortable, options = {}) if params[:sort_by] && params[:order] - validate_params(sortable) + validate_params(sortable, params) store_sort(sortable) - return "#{params.delete(:sort_by)} #{params.delete(:order)}" + return "#{params[:sort_by]} #{params[:order]}" else if session[:sortable_columns] && session[:sortable_columns][sortable.to_s.downcase.to_sym] column = session[:sortable_columns][sortable.to_s.downcase.to_sym].keys.first @@ -17,12 +17,25 @@ def sortable_order(sortable, options = {}) end end -private - - def validate_params(sortable) - raise ParameterError.new("#{sortable} has no column \"#{params[:sort_by]}\".") unless sortable.column_names.include?(params[:sort_by]) - raise ParameterError.new("Order must be \"asc\" or \"desc\"") unless params[:order] == "asc" || params[:order] == "desc" + def sortable_attributes_and_methods( sortable ) + columns = sortable.column_names + columns += sortable.sortable_methods.to_a if sortable.respond_to?( :sortable_methods ) + columns.map{ |c| c.to_s } + end + + def validate_params(sortable, params) + raise ParameterError.new("#{sortable} has no column or sortable_method \"#{params[:sort_by]}\". \n\nIf you're trying to sort by an instance method that isn't a column name (e.g. a value from an associated table), you must define \n\n\tsortable_instance_methods :my_method_1, :my_method_2 \n\nin your model class. Don't forget to include it as a column in your query too!") unless SortableColumns.sortable_attributes_and_methods(sortable).include?(params[:sort_by].to_s) + raise ParameterError.new("Order must be \"asc\" or \"desc\" - you gave #{params[:order]}") unless params[:order].blank? || ["asc","desc"].include?(params[:order].to_s.downcase) + end + + + def store_params + @params = params.clone - [ :controller, :action, :authenticity_token, :page, :format, :per_page ] end + + module_function :sortable_attributes_and_methods, :validate_params + +private def store_sort(sortable) session[:sortable_columns] ||= Hash.new