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,
  :default_order => :asc,
  :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.



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

def initialize(collection, opts = {})
  @collection = collection || []
  self.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.



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

def current_page
  @current_page
end

#original_countObject (readonly)

Returns the value of attribute original_count.



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

def original_count
  @original_count
end

#per_pageObject

Returns the value of attribute per_page.



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

def per_page
  @per_page
end

#searchable_columnsObject

Returns the value of attribute searchable_columns.



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

def searchable_columns
  @searchable_columns
end

#searchesObject (readonly)

Returns the value of attribute searches.



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

def searches
  @searches
end

#total_pagesObject (readonly)

Returns the value of attribute total_pages.



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

def total_pages
  @total_pages
end

Class Method Details

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



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

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



154
155
156
157
158
159
160
# File 'lib/magic_grid/collection.rb', line 154

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

#apply_all_operations(collection) ⇒ Object



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

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
144
# File 'lib/magic_grid/collection.rb', line 138

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

#apply_filter_callback(callback) ⇒ Object



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

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

#apply_pagination(current_page) ⇒ Object



192
193
194
195
196
# File 'lib/magic_grid/collection.rb', line 192

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

#apply_search(q) ⇒ Object



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

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
  self
end

#apply_sort(col, dir) ⇒ Object



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

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

#bound_current_page(page, per_page, total_entries) ⇒ Object



271
272
273
274
275
276
277
278
279
280
# File 'lib/magic_grid/collection.rb', line 271

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



261
262
263
264
265
266
267
268
269
# File 'lib/magic_grid/collection.rb', line 261

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



257
258
259
# File 'lib/magic_grid/collection.rb', line 257

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

#column_namesObject



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

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



174
175
176
177
178
179
180
# File 'lib/magic_grid/collection.rb', line 174

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



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

def count_options
  @options[:count]
end

#default_paginate(collection, page, per_page) ⇒ Object



198
199
200
201
202
203
204
205
206
207
# File 'lib/magic_grid/collection.rb', line 198

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



166
167
168
169
170
171
172
# File 'lib/magic_grid/collection.rb', line 166

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)


162
163
164
# File 'lib/magic_grid/collection.rb', line 162

def has_post_filter?
  @collection.respond_to? :post_filter
end

#hash_stringObject



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

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

#options=(opts) ⇒ Object



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

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

#perform_pagination(collection) ⇒ Object



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

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



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

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



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

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

#search_using_where(collection, q) ⇒ Object



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

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
# 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)


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

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