Class: MagicGrid::Collection

Inherits:
Object
  • Object
show all
Defined in:
lib/magic_grid/collection.rb

Constant Summary collapse

DEFAULTS =
{
  :per_page               => 30,
  :searchable             => [],
  :search_method          => :search,
  :listener_handler       => nil,
  :default_col            => 0,
  :post_filter            => false,
  :collection_post_filter => true,
  :count                  => nil,
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(collection, opts = {}) ⇒ Collection

Returns a new instance of Collection.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/magic_grid/collection.rb', line 18

def initialize(collection, opts = {})
  @collection = collection || []
  @options = opts
  @current_page = 1
  @sorts = []
  @filter_callbacks = []
  @filters = []
  @searches = []
  @post_filters = []
  @post_filter_callbacks = []
  @paginations = []
  @searchable_columns = []
  @@kaminari_class = defined?(Kaminari) ? Kaminari : nil
end

Instance Attribute Details

#current_pageObject (readonly)

Returns the value of attribute current_page.



36
37
38
# File 'lib/magic_grid/collection.rb', line 36

def current_page
  @current_page
end

#optionsObject



41
42
43
# File 'lib/magic_grid/collection.rb', line 41

def options
  DEFAULTS.merge(@options || {})
end

#original_countObject (readonly)

Returns the value of attribute original_count.



36
37
38
# File 'lib/magic_grid/collection.rb', line 36

def original_count
  @original_count
end

#per_pageObject

Returns the value of attribute per_page.



36
37
38
# File 'lib/magic_grid/collection.rb', line 36

def per_page
  @per_page
end

#searchable_columnsObject

Returns the value of attribute searchable_columns.



35
36
37
# File 'lib/magic_grid/collection.rb', line 35

def searchable_columns
  @searchable_columns
end

#searchesObject (readonly)

Returns the value of attribute searches.



36
37
38
# File 'lib/magic_grid/collection.rb', line 36

def searches
  @searches
end

#total_pagesObject (readonly)

Returns the value of attribute total_pages.



36
37
38
# File 'lib/magic_grid/collection.rb', line 36

def total_pages
  @total_pages
end

Class Method Details

.create_or_reuse(collection, opts = {}) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/magic_grid/collection.rb', line 49

def self.create_or_reuse(collection, opts = {})
  if collection.is_a?(self)
    collection.options = opts
    collection
  else
    Collection.new(collection, opts)
  end
end

Instance Method Details

#add_post_filter_callback(callback) ⇒ Object



152
153
154
155
156
157
# File 'lib/magic_grid/collection.rb', line 152

def add_post_filter_callback(callback)
  if callback.respond_to? :call
    @reduced_collection = nil
    @post_filter_callbacks << callback
  end
end

#apply_all_operations(collection) ⇒ Object



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/magic_grid/collection.rb', line 227

def apply_all_operations(collection)
  @sorts.each do |ordering|
    collection = collection.order(ordering)
  end
  if @filter_callbacks.empty?
    @filters.each do |hsh|
      collection = collection.where(hsh)
    end
  else
    @filter_callbacks.each do |callback|
      collection = callback.call(collection)
    end
  end
  @searches.each do |query|
    collection = perform_search(collection, query)
  end
  # Do collection filter first, may convert from AR to Array
  @post_filters.each do |filter|
    collection = collection.__send__(filter)
  end
  @post_filter_callbacks.each do |callback|
    collection = callback.call(collection)
  end
  # Paginate at the very end, after all sorting, filtering, etc..
  perform_pagination(collection)
end

#apply_filter(filters = {}) ⇒ Object



138
139
140
141
142
143
# File 'lib/magic_grid/collection.rb', line 138

def apply_filter(filters = {})
  if filterable? and not filters.empty?
    @reduced_collection = nil
    @filters << filters
  end
end

#apply_filter_callback(callback) ⇒ Object



145
146
147
148
149
150
# File 'lib/magic_grid/collection.rb', line 145

def apply_filter_callback(callback)
  if callback.respond_to? :call
    @reduced_collection = nil
    @filter_callbacks << callback
  end
end

#apply_pagination(current_page) ⇒ Object



189
190
191
192
# File 'lib/magic_grid/collection.rb', line 189

def apply_pagination(current_page)
  @current_page = current_page
  @reduced_collection = nil
end

#apply_search(q) ⇒ Object



116
117
118
119
120
121
122
123
124
125
# File 'lib/magic_grid/collection.rb', line 116

def apply_search(q)
  if q and not q.empty?
    if searchable?
      @reduced_collection = nil
      @searches << q
    else
      MagicGrid.logger.warn "#{self.class.name}: Ignoring searchable fields on collection"
    end
  end
end

#apply_sort(col, dir) ⇒ Object



103
104
105
106
107
108
# File 'lib/magic_grid/collection.rb', line 103

def apply_sort(col, dir)
  if sortable? and col.sortable?
    @reduced_collection = nil
    @sorts << "#{col.custom_sql} #{dir}"
  end
end

#bound_current_page(page, per_page, total_entries) ⇒ Object



268
269
270
271
272
273
274
275
276
277
# File 'lib/magic_grid/collection.rb', line 268

def bound_current_page(page, per_page, total_entries)
  pages = calculate_total_pages(per_page, total_entries)
  if page < 1
    1
  elsif page > pages
    pages
  else
    page
  end
end

#calculate_total_pages(per_page, total_entries) ⇒ Object



258
259
260
261
262
263
264
265
266
# File 'lib/magic_grid/collection.rb', line 258

def calculate_total_pages(per_page, total_entries)
  pages = total_entries / per_page
  pages += 1 if total_entries % per_page > 0
  if pages < 1
    1
  else
    pages
  end
end

#collectionObject



254
255
256
# File 'lib/magic_grid/collection.rb', line 254

def collection
  @reduced_collection ||= apply_all_operations(@collection)
end

#column_namesObject



58
59
60
61
62
63
# File 'lib/magic_grid/collection.rb', line 58

def column_names
  @collection.table.columns.map{|c| c[:name]}
rescue
  MagicGrid.logger.debug("Given collection doesn't respond to #table well: #{$!}")
  []
end

#count(collection = nil) ⇒ Object



171
172
173
174
175
176
177
# File 'lib/magic_grid/collection.rb', line 171

def count(collection = nil)
  count_or_hash = collection || @collection
  while count_or_hash.respond_to? :count
    count_or_hash = count_or_hash.send :count, *(Array([count_options]).compact)
  end
  count_or_hash
end

#count_optionsObject



45
46
47
# File 'lib/magic_grid/collection.rb', line 45

def count_options
  options[:count]
end

#default_paginate(collection, page, per_page) ⇒ Object



194
195
196
197
198
199
200
201
202
203
# File 'lib/magic_grid/collection.rb', line 194

def default_paginate(collection, page, per_page)
  collection = collection.to_enum
  collection = collection.each_slice(@per_page)
  collection = collection.drop(@current_page - 1)
  collection = collection.first.to_a
  class << collection
    attr_accessor :current_page, :total_pages, :original_count
  end
  collection
end

#enable_post_filter(yes = true) ⇒ Object



163
164
165
166
167
168
169
# File 'lib/magic_grid/collection.rb', line 163

def enable_post_filter(yes = true)
  @reduced_collection = nil
  if yes and has_post_filter?
    @post_filters << :post_filter
  end
  self
end

#filterable?Boolean

Returns:

  • (Boolean)


134
135
136
# File 'lib/magic_grid/collection.rb', line 134

def filterable?
  @collection.respond_to? :where
end

#has_post_filter?Boolean

Returns:

  • (Boolean)


159
160
161
# File 'lib/magic_grid/collection.rb', line 159

def has_post_filter?
  @collection.respond_to? :post_filter
end

#hash_stringObject



73
74
75
76
77
78
79
# File 'lib/magic_grid/collection.rb', line 73

def hash_string
  if @collection.respond_to? :to_sql
    @collection.to_sql.hash.abs.to_s(36)
  else
    options.hash.abs.to_s(36)
  end
end

#perform_pagination(collection) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/magic_grid/collection.rb', line 205

def perform_pagination(collection)
  return collection unless @per_page

  total_entries = count(collection)
  @current_page = bound_current_page(@current_page,
                                     @per_page,
                                     total_entries)

  if collection.respond_to? :paginate
    collection.paginate(:page => @current_page,
                        :per_page => @per_page,
                        :total_entries => total_entries)
  elsif collection.respond_to? :page
    collection.page(@current_page).per(@per_page)
  elsif collection.is_a?(Array) and @@kaminari_class
     @@kaminari_class.paginate_array(collection).
                      page(@current_page).per(@per_page)
  else
     default_paginate(collection, @current_page, @per_page)
  end
end

#perform_search(collection, q) ⇒ Object



127
128
129
130
131
132
# File 'lib/magic_grid/collection.rb', line 127

def perform_search(collection, q)
  search_using_builtin(collection, q)
rescue
  MagicGrid.logger.debug "Given collection doesn't respond to #{options[:search_method]} well"
  search_using_where(collection, q)
end

#quote_column_name(col) ⇒ Object



65
66
67
68
69
70
71
# File 'lib/magic_grid/collection.rb', line 65

def quote_column_name(col)
  if col.is_a? Symbol and @collection.respond_to? :quoted_table_name
    "#{quoted_table_name}.#{@collection.connection.quote_column_name(col.to_s)}"
  else
    col.to_s
  end
end

#search_using_builtin(collection, q) ⇒ Object



81
82
83
# File 'lib/magic_grid/collection.rb', line 81

def search_using_builtin(collection, q)
  collection.__send__(options[:search_method], q)
end

#search_using_where(collection, q) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/magic_grid/collection.rb', line 85

def search_using_where(collection, q)
  result = collection
  unless searchable_columns.empty?
    begin
      search_cols = searchable_columns.map {|c| c.custom_sql || c.name }
      clauses = search_cols.map {|c| c << " LIKE :search" }.join(" OR ")
      result = collection.where(clauses, {:search => "%#{q}%"})
    rescue
      MagicGrid.logger.debug "Given collection doesn't respond to :where well"
    end
  end
  result
end

#searchable?Boolean

Returns:

  • (Boolean)


110
111
112
113
114
# File 'lib/magic_grid/collection.rb', line 110

def searchable?
  (filterable? and not searchable_columns.empty?) or
    (options[:search_method] and
     @collection.respond_to? options[:search_method])
end

#sortable?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/magic_grid/collection.rb', line 99

def sortable?
  @collection.respond_to?(:order)
end