lib/magic_grid/definition.rb in magic_grid-0.10.4 vs lib/magic_grid/definition.rb in magic_grid-0.11.0

- old
+ new

@@ -1,20 +1,24 @@ -#require 'will_paginate/view_helpers/action_view' +require 'magic_grid/logger' +require 'magic_grid/collection' module MagicGrid class Definition - #include WillPaginate::ActionView - attr_accessor :columns, :collection, :magic_id, :options, :params, + attr_reader :columns, :magic_id, :options, :params, :current_sort_col, :current_order, :default_order, :per_page + def collection + @collection.collection + end + DEFAULTS = { :class => [], :top_pager => false, :bottom_pager => true, :remote => false, :per_page => 30, - :searchable => false, + :searchable => [], :search_method => :search, :min_search_length => 3, :id => false, :searcher => false, :needs_searcher => false, @@ -54,17 +58,17 @@ raise "I have no idea what that is, but it's not a Hash or an Array" end @default_order = @options[:default_order] @params = controller && controller.params || {} @per_page = @options[:per_page] - @collection = collection + @collection = Collection[collection, self] begin #if @collection.respond_to? :table table_name = @collection.quoted_table_name table_columns = @collection.table.columns.map {|c| c.name} rescue - Rails.logger.debug "Given collection doesn't respond to :table well" + MagicGrid.logger.debug "Given collection doesn't respond to :table well" table_name = nil table_columns = @columns.each_index.to_a end i = 0 hash = [] @@ -88,110 +92,72 @@ else @magic_id = hash.join.hash.abs.to_s(36) @magic_id << @collection.to_sql.hash.abs.to_s(36) if @collection.respond_to? :to_sql end @current_sort_col = sort_col_i = param(:col, @options[:default_col]).to_i - if @collection.respond_to?(:order) and @columns.count > sort_col_i and @columns[sort_col_i].has_key?(:sql) + if @collection.sortable? and @columns.count > sort_col_i and @columns[sort_col_i].has_key?(:sql) sort_col = @columns[sort_col_i][:sql] @current_order = order(param(:order, @default_order)) sort_dir = order_sql(@current_order) - @collection = @collection.order("#{sort_col} #{sort_dir}") + @collection.apply_sort(sort_col, sort_dir) else - Rails.logger.debug "#{self.class.name}: Ignoring sorting on non-AR collection" + MagicGrid.logger.debug "#{self.class.name}: Ignoring sorting on non-AR collection" end - @options[:searchable] = [] if @options[:searchable] and not @options[:searchable].kind_of? Array - - if @collection.respond_to?(:where) or @options[:listener_handler].respond_to?(:call) + if @collection.filterable? or @options[:listener_handler].respond_to?(:call) if @options[:listener_handler].respond_to? :call - @collection = @options[:listener_handler].call(@collection) + @collection.apply_filter_callback @options[:listener_handler] else @options[:listeners].each_pair do |key, value| if @params[value] and not @params[value].to_s.empty? - @collection = @collection.where(value => @params[value]) + @collection.apply_filter(value => @params[value]) end end end else unless @options[:listeners].empty? - Rails.logger.warn "#{self.class.name}: Ignoring listener on dumb collection" + MagicGrid.logger.warn "#{self.class.name}: Ignoring listener on dumb collection" @options[:listeners] = {} end end + + @options[:searchable] = Array(@options[:searchable]) @options[:current_search] ||= param(:q) - if (@collection.respond_to?(:where) or - (@options[:search_method] and @collection.respond_to?(@options[:search_method]))) - if param(:q) and not param(:q).empty? and @options[:searchable] - orig_collection = @collection - begin - @collection = @collection.__send__(@options[:search_method], param(:q)) - rescue - Rails.logger.debug "Given collection doesn't respond to #{@options[:search_method]} well" - @collection = orig_collection - search_cols = @options[:searchable].map do |searchable| - case searchable - when Symbol - known = @columns.find {|col| col[:col] == searchable} - if known and known.key?(:sql) - known[:sql] - else - "#{table_name}.#{@collection.connection.quote_column_name(searchable.to_s)}" - end - when Integer - @columns[searchable][:sql] - when String - searchable - else - raise "Searchable must be identifiable" - end - end - unless search_cols.empty? - begin - clauses = search_cols.map {|c| c << " LIKE :search" }.join(" OR ") - @collection = @collection.where(clauses, {:search => "%#{param(:q)}%"}) - rescue - Rails.logger.debug "Given collection doesn't respond to :where well" - @collection = orig_collection - end - end - end + if @collection.searchable? + if param(:q) and not param(:q).empty? and not @options[:searchable].empty? + @collection.apply_search(param(:q)) end else - if @options[:searchable] or param(:q) - Rails.logger.warn "#{self.class.name}: Ignoring searchable fields on non-AR collection" + if not @options[:searchable].empty? or param(:q) + MagicGrid.logger.warn "#{self.class.name}: Ignoring searchable fields on non-AR collection" end - @options[:searchable] = false + @options[:searchable] = [] end - if not @options[:searcher] and @options[:searchable] - @options[:needs_searcher] = true - @options[:searcher] = param_key(:searcher) - end + # Do collection filter first, may convert from AR to Array - if @options[:collection_post_filter?] and @collection.respond_to?(:post_filter) - @collection = @collection.post_filter(controller) + if @options[:collection_post_filter?] and @collection.has_post_filter? + @collection.apply_post_filter end if @options[:post_filter] and @options[:post_filter].respond_to?(:call) - @collection = @options[:post_filter].call(@collection) + @collection.apply_filter_callback @options[:post_filter] end # Paginate at the very end, after all sorting, filtering, etc.. - if @per_page - if @collection.respond_to? :paginate - @collection = @collection.paginate(:page => current_page, - :per_page => @per_page) - elsif @collection.respond_to? :page - @collection = @collection.page(current_page).per(@per_page) - elsif @collection.is_a?(Array) and Module.const_defined?(:Kaminari) - @collection = Kaminari.paginate_array(@collection).page(current_page).per(@per_page) - else - original = @collection - @collection = @collection.to_enum.each_slice(@per_page).drop(current_page - 1).first.to_a - class << @collection - attr_accessor :current_page, :total_pages, :original_count - end - @collection.current_page = current_page - @collection.original_count = original.count - @collection.total_pages = original.count / @per_page - end + @collection.apply_pagination(current_page, @per_page) + end + + def searchable? + @collection.searchable? and not @options[:searchable].empty? + end + + def needs_searcher? + @options[:needs_searcher] or (searchable? and not @options[:searcher]) + end + + def searcher + if needs_searcher? + param_key(:searcher) + else + @options[:searcher] end end def param_key(key) "#{@magic_id}_#{key}".to_sym