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
# 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 = []
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

#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



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

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

#apply_all_operations(collection) ⇒ Object



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/magic_grid/collection.rb', line 221

def apply_all_operations(collection)
  @sorts.each do |ordering|
    collection = collection.order(ordering)
  end
  @filter_callbacks.each do |callback|
    collection = callback.call(collection)
  end
  @filters.each do |hsh|
    collection = collection.where(hsh)
  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



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

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

#apply_filter_callback(callback) ⇒ Object



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

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

#apply_pagination(current_page) ⇒ Object



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

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

#apply_search(q) ⇒ Object



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

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



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

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

#collectionObject



245
246
247
# File 'lib/magic_grid/collection.rb', line 245

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

#column_namesObject



55
56
57
58
59
60
# File 'lib/magic_grid/collection.rb', line 55

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



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

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



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

def count_options
  @options[:count]
end

#default_paginate(collection, page, per_page) ⇒ Object



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

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



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

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)


132
133
134
# File 'lib/magic_grid/collection.rb', line 132

def filterable?
  @collection.respond_to? :where
end

#has_post_filter?Boolean

Returns:

  • (Boolean)


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

def has_post_filter?
  @collection.respond_to? :post_filter
end

#hash_stringObject



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

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



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

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

#perform_pagination(collection) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/magic_grid/collection.rb', line 207

def perform_pagination(collection)
  return collection unless @per_page

  if collection.respond_to? :paginate
    collection.paginate(page: @current_page, per_page: @per_page, total_entries: count(collection))
  elsif collection.respond_to? :page
    collection.page(@current_page).per(@per_page)
  elsif collection.is_a?(Array) and Module.const_defined?(:Kaminari)
     Kaminari.paginate_array(collection).page(@current_page).per(@per_page)
  else
     default_paginate(collection, @current_page, @per_page)
  end
end

#perform_search(collection, q) ⇒ Object



125
126
127
128
129
130
# File 'lib/magic_grid/collection.rb', line 125

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



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

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



78
79
80
# File 'lib/magic_grid/collection.rb', line 78

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

#search_using_where(collection, q) ⇒ Object



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

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)


108
109
110
111
# File 'lib/magic_grid/collection.rb', line 108

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

#sortable?Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/magic_grid/collection.rb', line 96

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