lib/magic_grid/definition.rb in magic_grid-0.11.1 vs lib/magic_grid/definition.rb in magic_grid-0.12.0

- old
+ new

@@ -1,158 +1,105 @@ require 'magic_grid/logger' require 'magic_grid/collection' +require 'magic_grid/column' +require 'active_support/core_ext' module MagicGrid class Definition - attr_reader :columns, :magic_id, :options, :params, - :current_sort_col, :current_order, :default_order, :per_page + attr_reader :columns, :options, :params, + :current_sort_col, :current_order, :default_order def magic_collection @collection end def collection @collection.collection end DEFAULTS = { - :class => [], - :top_pager => false, - :bottom_pager => true, - :remote => false, - :per_page => 30, - :searchable => [], - :search_method => :search, - :min_search_length => 3, - :id => false, - :searcher => false, - :needs_searcher => false, - :live_search => false, - :current_search => nil, - :listeners => {}, - :listener_handler => nil, - :default_col => 0, - :default_order => :asc, - :empty_header => false, - :empty_footer => false, - :post_filter => false, - :collection_post_filter? => true, - :default_ajax_handler => true, - :search_button => false, - :searcher_size => nil, + class: [], + top_pager: false, + bottom_pager: true, + remote: false, + min_search_length: 3, + id: false, + searcher: false, + needs_searcher: false, + live_search: false, + listeners: {}, + collapse_empty_header: false, + collapse_empty_footer: false, + default_ajax_handler: true, + search_button: false, + searcher_size: nil, } def self.runtime_defaults # run these lazily to catch any late I18n path changes - DEFAULTS.merge( - :if_empty => I18n.t("magic_grid.no_results").capitalize, # "No results found." - :searcher_label => I18n.t("magic_grid.search.label").capitalize + ': ', # "Search: " - :searcher_tooltip =>I18n.t("magic_grid.search.tooltip"), # "type.. + <return>" - :searcher_button =>I18n.t("magic_grid.search.button").capitalize, # "Search" + DEFAULTS.merge(Collection::DEFAULTS) + .merge( + if_empty: I18n.t("magic_grid.no_results").capitalize, # "No results found." + searcher_label: I18n.t("magic_grid.search.label").capitalize + ': ', # "Search: " + searcher_tooltip: I18n.t("magic_grid.search.tooltip"), # "type.. + <return>" + searcher_button: I18n.t("magic_grid.search.button").capitalize, # "Search" ) end - def initialize(cols_or_opts, collection = nil, controller = nil, opts = {}) + def self.normalize_columns_options(cols_or_opts, opts) if cols_or_opts.is_a? Hash - @options = self.class.runtime_defaults.merge(cols_or_opts.reject {|k| k == :cols}) - @columns = cols_or_opts.fetch(:cols, []) + options = runtime_defaults.merge(cols_or_opts.reject {|k| k == :cols}) + columns = cols_or_opts.fetch(:cols, []) elsif cols_or_opts.is_a? Array - @options = self.class.runtime_defaults.merge opts - @columns = cols_or_opts + options = runtime_defaults.merge opts + columns = cols_or_opts else - raise "I have no idea what that is, but it's not a Hash or an Array" + raise "I have no idea what that is, but it's not a columns list or options hash" end + [options, columns] + end + + def initialize(cols_or_opts, collection = nil, controller = nil, opts = {}) + @options, @columns = *self.class.normalize_columns_options(cols_or_opts, opts) @default_order = @options[:default_order] @params = controller && controller.params || {} - @per_page = @options[:per_page] - @collection = Collection[collection, self] - begin - #if @collection.respond_to? :table - table_name = @collection.quoted_table_name - table_columns = @collection.column_names - rescue - msg = "Given collection doesn't respond to :quoted_table_name or :table well: " - MagicGrid.logger.debug("#{msg} - #{$!}") - table_name = nil - table_columns = @columns.each_index.to_a - end - i = 0 - hash = [] - @columns.map! do |c| - if c.is_a? Symbol - c = {:col => c} - elsif c.is_a? String - c = {:label => c} - end - c[:id] = i - i += 1 - if c.key?(:col) and c[:col].is_a?(Symbol) and table_columns.include?(c[:col]) - c[:sql] = "#{table_name}.#{@collection.quote_column_name(c[:col].to_s)}" unless c.key?(:sql) - end - c[:label] = c[:col].to_s.titleize if not c.key? :label - hash << c[:label] - c - end - if @options[:id] - @magic_id = @options[:id] - 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.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.apply_sort(sort_col, sort_dir) - else - MagicGrid.logger.debug "#{self.class.name}: Ignoring sorting on non-AR collection" - end - if @collection.filterable? or @options[:listener_handler].respond_to?(:call) - if @options[:listener_handler].respond_to? :call - @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.apply_filter(value => @params[value]) - end - end - end - else - unless @options[:listeners].empty? - MagicGrid.logger.warn "#{self.class.name}: Ignoring listener on dumb collection" - @options[:listeners] = {} - end - end + @collection = Collection.create_or_reuse collection, @options - @options[:searchable] = Array(@options[:searchable]) - @options[:current_search] ||= param(:q) - if @collection.searchable? - if param(:q) and not param(:q).empty? and not @options[:searchable].empty? - @collection.apply_search(param(:q)) - end - else - if not @options[:searchable].empty? or param(:q) - MagicGrid.logger.warn "#{self.class.name}: Ignoring searchable fields on non-AR collection" - end - @options[:searchable] = [] - end + @columns = Column.columns_for_collection(@collection, + @columns, + @options[:searchable]) - # Do collection filter first, may convert from AR to Array - if @options[:collection_post_filter?] and @collection.has_post_filter? - @collection.apply_post_filter + @current_sort_col = param(:col, @options[:default_col]).to_i + unless (0...@columns.count).cover? @current_sort_col + @current_sort_col = @options[:default_col] end - if @options[:post_filter] and @options[:post_filter].respond_to?(:call) - @collection.apply_filter_callback @options[:post_filter] - end - # Paginate at the very end, after all sorting, filtering, etc.. - @collection.apply_pagination(current_page, @per_page) + @current_order = order(param(:order, @default_order)) + @collection.apply_sort(@columns[@current_sort_col], order_sql(@current_order)) + + filter_keys = @options[:listeners].values + filters = @params.slice(*filter_keys).reject {|k,v| v.to_s.empty? } + @collection.apply_filter filters + @collection.apply_pagination(current_page) + @collection.apply_search current_search + + @collection.per_page = @options[:per_page] + @collection.apply_filter_callback @options[:listener_handler] + @collection.enable_post_filter @options[:collection_post_filter] + @collection.add_post_filter_callback @options[:post_filter] end + def current_search + param(:q) + end + + def magic_id + @options[:id] || (Column.hash_string(@columns) + @collection.hash_string) + end + def searchable? - @collection.searchable? and not @options[:searchable].empty? + @collection.searchable? end def needs_searcher? @options[:needs_searcher] or (searchable? and not @options[:searcher]) end @@ -164,18 +111,18 @@ @options[:searcher] end end def param_key(key) - "#{@magic_id}_#{key}".to_sym + "#{magic_id}_#{key}".to_sym end def param(key, default=nil) @params.fetch(param_key(key), default) end def base_params - @params.merge :magic_grid_id => @magic_id + @params.merge magic_grid_id: magic_id end def current_page [param(:page, 1).to_i, 1].max end