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