magic_grid 0.11.1 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -0
- data/Rakefile +2 -2
- data/lib/assets/javascripts/magic_grid.js +7 -6
- data/lib/magic_grid/collection.rb +115 -67
- data/lib/magic_grid/column.rb +93 -0
- data/lib/magic_grid/definition.rb +67 -120
- data/lib/magic_grid/helpers.rb +5 -249
- data/lib/magic_grid/html_grid.rb +275 -0
- data/lib/magic_grid/version.rb +1 -1
- data/spec/collection_spec.rb +139 -8
- data/spec/column_spec.rb +72 -0
- data/spec/definition_spec.rb +63 -35
- data/spec/helpers_spec.rb +71 -93
- data/spec/html_grid_spec.rb +117 -0
- data/spec/spec_helper.rb +36 -4
- data/test/dummy/app/controllers/users_controller.rb +4 -0
- metadata +121 -115
data/README.md
CHANGED
@@ -2,6 +2,7 @@ MagicGrid
|
|
2
2
|
=========
|
3
3
|
|
4
4
|
[![Build Status](https://secure.travis-ci.org/rmg/magic_grid.png?branch=master)](http://travis-ci.org/rmg/magic_grid)
|
5
|
+
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/rmg/magic_grid)
|
5
6
|
|
6
7
|
Easy collection display grid with column sorting and pagination.
|
7
8
|
|
data/Rakefile
CHANGED
@@ -127,8 +127,11 @@ $(function () {
|
|
127
127
|
var $grid = $(this),
|
128
128
|
listeners = $grid.data("listeners"),
|
129
129
|
grid_id = this.id,
|
130
|
-
|
131
|
-
|
130
|
+
mark_as_ready = function () {
|
131
|
+
$(this).addClass("ready");
|
132
|
+
},
|
133
|
+
request_grid_if_ready = function () {
|
134
|
+
if (! $(this).hasClass("ready")) {
|
132
135
|
return;
|
133
136
|
}
|
134
137
|
var base_url = $grid.data("current").split("?", 2)[0];
|
@@ -143,10 +146,8 @@ $(function () {
|
|
143
146
|
}
|
144
147
|
};
|
145
148
|
for (var k in listeners) {
|
146
|
-
$("#" + k).on("change",
|
147
|
-
$("#" + k).on("ready",
|
148
|
-
$(this).addClass("ready");
|
149
|
-
});
|
149
|
+
$("#" + k).on("change", request_grid_if_ready);
|
150
|
+
$("#" + k).on("ready", mark_as_ready);
|
150
151
|
}
|
151
152
|
});
|
152
153
|
|
@@ -4,9 +4,20 @@ require 'magic_grid/logger'
|
|
4
4
|
module MagicGrid
|
5
5
|
class Collection
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
DEFAULTS = {
|
8
|
+
per_page: 30,
|
9
|
+
searchable: [],
|
10
|
+
search_method: :search,
|
11
|
+
listener_handler: nil,
|
12
|
+
default_col: 0,
|
13
|
+
default_order: :asc,
|
14
|
+
post_filter: false,
|
15
|
+
collection_post_filter: true,
|
16
|
+
}
|
17
|
+
|
18
|
+
def initialize(collection, opts = {})
|
19
|
+
@collection = collection || []
|
20
|
+
self.options = opts
|
10
21
|
@current_page = 1
|
11
22
|
@sorts = []
|
12
23
|
@filter_callbacks = []
|
@@ -15,58 +26,61 @@ module MagicGrid
|
|
15
26
|
@post_filters = []
|
16
27
|
@post_filter_callbacks = []
|
17
28
|
@paginations = []
|
29
|
+
@searchable_columns = []
|
18
30
|
end
|
19
31
|
|
20
|
-
delegate :quoted_table_name, :map, :count, :
|
32
|
+
delegate :quoted_table_name, :map, :count, to: :collection
|
21
33
|
|
22
|
-
attr_accessor :
|
23
|
-
attr_reader :current_page, :original_count, :total_pages
|
34
|
+
attr_accessor :searchable_columns
|
35
|
+
attr_reader :current_page, :original_count, :total_pages, :per_page, :searches
|
24
36
|
|
25
|
-
def
|
37
|
+
def options=(opts)
|
38
|
+
@options = DEFAULTS.merge(opts || {})
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.create_or_reuse(collection, opts = {})
|
26
42
|
if collection.is_a?(self)
|
27
|
-
collection.
|
43
|
+
collection.options = opts
|
28
44
|
collection
|
29
45
|
else
|
30
|
-
Collection.new(collection,
|
46
|
+
Collection.new(collection, opts)
|
31
47
|
end
|
32
48
|
end
|
33
49
|
|
34
50
|
def column_names
|
35
|
-
@collection.table.columns.map
|
51
|
+
@collection.table.columns.map{|c| c[:name]}
|
52
|
+
rescue
|
53
|
+
MagicGrid.logger.debug("Given collection doesn't respond to #table well: #{$!}")
|
54
|
+
[]
|
36
55
|
end
|
37
56
|
|
38
57
|
def quote_column_name(col)
|
39
|
-
@collection.
|
58
|
+
if col.is_a? Symbol and @collection.respond_to? :quoted_table_name
|
59
|
+
"#{quoted_table_name}.#{@collection.connection.quote_column_name(col.to_s)}"
|
60
|
+
else
|
61
|
+
col.to_s
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def hash_string
|
66
|
+
if @collection.respond_to? :to_sql
|
67
|
+
@collection.to_sql.hash.abs.to_s(36)
|
68
|
+
else
|
69
|
+
@options.hash.abs.to_s(36)
|
70
|
+
end
|
40
71
|
end
|
41
72
|
|
42
73
|
def search_using_builtin(collection, q)
|
43
|
-
collection.__send__(@
|
74
|
+
collection.__send__(@options[:search_method], q)
|
44
75
|
end
|
45
76
|
|
46
77
|
def search_using_where(collection, q)
|
47
78
|
result = collection
|
48
|
-
|
49
|
-
case searchable
|
50
|
-
when Symbol
|
51
|
-
known = @grid.columns.find {|col| col[:col] == searchable}
|
52
|
-
if known and known.key?(:sql)
|
53
|
-
known[:sql]
|
54
|
-
else
|
55
|
-
"#{@collection.table_name}.#{quote_column_name(searchable)}"
|
56
|
-
end
|
57
|
-
when Integer
|
58
|
-
@grid.columns[searchable][:sql]
|
59
|
-
when String
|
60
|
-
searchable
|
61
|
-
else
|
62
|
-
raise "Searchable must be identifiable"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
unless search_cols.empty?
|
79
|
+
unless searchable_columns.empty?
|
67
80
|
begin
|
81
|
+
search_cols = searchable_columns.map {|c| c.custom_sql || c.name }
|
68
82
|
clauses = search_cols.map {|c| c << " LIKE :search" }.join(" OR ")
|
69
|
-
result = collection.where(clauses, {:
|
83
|
+
result = collection.where(clauses, {search: "%#{q}%"})
|
70
84
|
rescue
|
71
85
|
MagicGrid.logger.debug "Given collection doesn't respond to :where well"
|
72
86
|
end
|
@@ -79,25 +93,34 @@ module MagicGrid
|
|
79
93
|
end
|
80
94
|
|
81
95
|
def apply_sort(col, dir)
|
82
|
-
|
83
|
-
|
96
|
+
if sortable? and col.sortable?
|
97
|
+
@reduced_collection = nil
|
98
|
+
@sorts << "#{col.custom_sql} #{dir}"
|
99
|
+
end
|
84
100
|
self
|
85
101
|
end
|
86
102
|
|
87
103
|
def searchable?
|
88
|
-
filterable?
|
104
|
+
(filterable? and not searchable_columns.empty?) or
|
105
|
+
(@options[:search_method] and @collection.respond_to? @options[:search_method])
|
89
106
|
end
|
90
107
|
|
91
108
|
def apply_search(q)
|
92
|
-
|
93
|
-
|
109
|
+
if q and not q.empty?
|
110
|
+
if searchable?
|
111
|
+
@reduced_collection = nil
|
112
|
+
@searches << q
|
113
|
+
else
|
114
|
+
MagicGrid.logger.warn "#{self.class.name}: Ignoring searchable fields on collection"
|
115
|
+
end
|
116
|
+
end
|
94
117
|
self
|
95
118
|
end
|
96
119
|
|
97
120
|
def perform_search(collection, q)
|
98
121
|
search_using_builtin(collection, q)
|
99
122
|
rescue
|
100
|
-
MagicGrid.logger.debug "Given collection doesn't respond to #{@
|
123
|
+
MagicGrid.logger.debug "Given collection doesn't respond to #{@options[:search_method]} well"
|
101
124
|
search_using_where(collection, q)
|
102
125
|
end
|
103
126
|
|
@@ -106,7 +129,7 @@ module MagicGrid
|
|
106
129
|
end
|
107
130
|
|
108
131
|
def apply_filter(filters = {})
|
109
|
-
if
|
132
|
+
if filterable? and not filters.empty?
|
110
133
|
@reduced_collection = nil
|
111
134
|
@filters << filters
|
112
135
|
end
|
@@ -121,45 +144,73 @@ module MagicGrid
|
|
121
144
|
self
|
122
145
|
end
|
123
146
|
|
147
|
+
def add_post_filter_callback(callback)
|
148
|
+
if callback.respond_to? :call
|
149
|
+
@reduced_collection = nil
|
150
|
+
@post_filter_callbacks << callback
|
151
|
+
end
|
152
|
+
self
|
153
|
+
end
|
154
|
+
|
124
155
|
def has_post_filter?
|
125
156
|
@collection.respond_to? :post_filter
|
126
157
|
end
|
127
158
|
|
128
|
-
def
|
159
|
+
def enable_post_filter(yes = true)
|
129
160
|
@reduced_collection = nil
|
130
|
-
|
161
|
+
if yes and has_post_filter?
|
162
|
+
@post_filters << :post_filter
|
163
|
+
end
|
131
164
|
self
|
132
165
|
end
|
133
166
|
|
134
|
-
def
|
135
|
-
|
136
|
-
|
137
|
-
|
167
|
+
def count(collection = nil)
|
168
|
+
count_or_hash = collection || @collection
|
169
|
+
while count_or_hash.respond_to? :count
|
170
|
+
count_or_hash = count_or_hash.count
|
171
|
+
end
|
172
|
+
count_or_hash
|
173
|
+
end
|
174
|
+
|
175
|
+
def per_page=(n)
|
176
|
+
@original_count = self.count @collection
|
177
|
+
@per_page = n
|
178
|
+
if @per_page
|
179
|
+
@total_pages = @original_count / @per_page
|
180
|
+
else
|
181
|
+
@total_pages = 1
|
138
182
|
end
|
139
|
-
self
|
140
183
|
end
|
141
184
|
|
142
|
-
def
|
143
|
-
@original_count = @collection.count
|
144
|
-
@total_pages = @original_count / per_page
|
185
|
+
def apply_pagination(current_page)
|
145
186
|
@current_page = current_page
|
187
|
+
@reduced_collection = nil
|
188
|
+
self
|
189
|
+
end
|
190
|
+
|
191
|
+
def default_paginate(collection, page, per_page)
|
192
|
+
collection = collection.to_enum
|
193
|
+
collection = collection.each_slice(@per_page)
|
194
|
+
collection = collection.drop(@current_page - 1)
|
195
|
+
collection = collection.first.to_a
|
196
|
+
class << collection
|
197
|
+
attr_accessor :current_page, :total_pages, :original_count
|
198
|
+
end
|
199
|
+
collection
|
200
|
+
end
|
201
|
+
|
202
|
+
def perform_pagination(collection)
|
203
|
+
return collection unless @per_page
|
204
|
+
|
146
205
|
if collection.respond_to? :paginate
|
147
|
-
collection
|
148
|
-
:per_page => per_page)
|
206
|
+
collection.paginate(page: @current_page, per_page: @per_page)
|
149
207
|
elsif collection.respond_to? :page
|
150
|
-
collection
|
208
|
+
collection.page(@current_page).per(@per_page)
|
151
209
|
elsif collection.is_a?(Array) and Module.const_defined?(:Kaminari)
|
152
|
-
|
210
|
+
Kaminari.paginate_array(collection).page(@current_page).per(@per_page)
|
153
211
|
else
|
154
|
-
|
155
|
-
collection = collection.each_slice(per_page)
|
156
|
-
collection = collection.drop(current_page - 1)
|
157
|
-
collection = collection.first.to_a
|
158
|
-
class << collection
|
159
|
-
attr_accessor :current_page, :total_pages, :original_count
|
160
|
-
end
|
212
|
+
default_paginate(collection, @current_page, @per_page)
|
161
213
|
end
|
162
|
-
collection
|
163
214
|
end
|
164
215
|
|
165
216
|
def apply_all_operations(collection)
|
@@ -175,23 +226,20 @@ module MagicGrid
|
|
175
226
|
@searches.each do |query|
|
176
227
|
collection = perform_search(collection, query)
|
177
228
|
end
|
229
|
+
# Do collection filter first, may convert from AR to Array
|
178
230
|
@post_filters.each do |filter|
|
179
231
|
collection = collection.__send__(filter)
|
180
232
|
end
|
181
233
|
@post_filter_callbacks.each do |callback|
|
182
234
|
collection = callback.call(collection)
|
183
235
|
end
|
184
|
-
|
185
|
-
|
186
|
-
end
|
187
|
-
collection
|
236
|
+
# Paginate at the very end, after all sorting, filtering, etc..
|
237
|
+
perform_pagination(collection)
|
188
238
|
end
|
189
239
|
|
190
240
|
def collection
|
191
241
|
@reduced_collection ||= apply_all_operations(@collection)
|
192
242
|
end
|
193
243
|
|
194
|
-
|
195
|
-
|
196
244
|
end
|
197
245
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module MagicGrid
|
2
|
+
class Column
|
3
|
+
|
4
|
+
def self.columns_for_collection(collection, columns, searchables)
|
5
|
+
columns.map.each_with_index { |c, i|
|
6
|
+
MagicGrid::Column.new(collection, c, i)
|
7
|
+
}.tap do |cols|
|
8
|
+
search_disabled = false
|
9
|
+
collection.searchable_columns = Array(searchables).map { |searchable|
|
10
|
+
case searchable
|
11
|
+
when Symbol
|
12
|
+
cols.find {|col| col.name == searchable} || FilterOnlyColumn.new(searchable, collection)
|
13
|
+
when Integer
|
14
|
+
cols[searchable]
|
15
|
+
when String
|
16
|
+
FilterOnlyColumn.new(searchable)
|
17
|
+
when true
|
18
|
+
nil
|
19
|
+
when false
|
20
|
+
search_disabled = true
|
21
|
+
nil
|
22
|
+
else
|
23
|
+
raise "Searchable must be identifiable: #{searchable}"
|
24
|
+
end
|
25
|
+
}.compact
|
26
|
+
collection.searchable_columns = [] if search_disabled
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.hash_string(column_or_columns)
|
31
|
+
Array(column_or_columns).map(&:label).join.hash.abs.to_s(36)
|
32
|
+
end
|
33
|
+
|
34
|
+
def label
|
35
|
+
@col[:label]
|
36
|
+
end
|
37
|
+
|
38
|
+
def sortable?
|
39
|
+
not custom_sql.blank?
|
40
|
+
end
|
41
|
+
|
42
|
+
def custom_sql
|
43
|
+
@col[:sql]
|
44
|
+
end
|
45
|
+
|
46
|
+
def id
|
47
|
+
@col[:id]
|
48
|
+
end
|
49
|
+
|
50
|
+
def name
|
51
|
+
@col[:col]
|
52
|
+
end
|
53
|
+
|
54
|
+
def html_classes
|
55
|
+
Array(@col[:class]).join ' '
|
56
|
+
end
|
57
|
+
|
58
|
+
def reader
|
59
|
+
@col[:to_s] || @col[:col]
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def initialize(collection, c, i)
|
64
|
+
@collection = collection
|
65
|
+
@col = case c
|
66
|
+
when Symbol
|
67
|
+
{col: c}
|
68
|
+
when String
|
69
|
+
{label: c}
|
70
|
+
else
|
71
|
+
c
|
72
|
+
end
|
73
|
+
@col[:id] = i
|
74
|
+
if @collection.column_names.include?(@col[:col])
|
75
|
+
@col[:sql] ||= @collection.quote_column_name(name)
|
76
|
+
end
|
77
|
+
@col[:label] ||= @col[:col].to_s.titleize
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
class FilterOnlyColumn < Column
|
83
|
+
attr_reader :name, :custom_sql
|
84
|
+
def initialize(name, collection = nil)
|
85
|
+
@name = name
|
86
|
+
if collection
|
87
|
+
@custom_sql = collection.quote_column_name(name)
|
88
|
+
else
|
89
|
+
@custom_sql = name
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'magic_grid/logger'
|
2
2
|
require 'magic_grid/collection'
|
3
|
+
require 'magic_grid/column'
|
4
|
+
require 'active_support/core_ext'
|
3
5
|
|
4
6
|
module MagicGrid
|
5
7
|
class Definition
|
6
|
-
attr_reader :columns, :
|
7
|
-
:current_sort_col, :current_order, :default_order
|
8
|
+
attr_reader :columns, :options, :params,
|
9
|
+
:current_sort_col, :current_order, :default_order
|
8
10
|
|
9
11
|
def magic_collection
|
10
12
|
@collection
|
@@ -15,142 +17,87 @@ module MagicGrid
|
|
15
17
|
end
|
16
18
|
|
17
19
|
DEFAULTS = {
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:default_col => 0,
|
34
|
-
:default_order => :asc,
|
35
|
-
:empty_header => false,
|
36
|
-
:empty_footer => false,
|
37
|
-
:post_filter => false,
|
38
|
-
:collection_post_filter? => true,
|
39
|
-
:default_ajax_handler => true,
|
40
|
-
:search_button => false,
|
41
|
-
:searcher_size => nil,
|
20
|
+
class: [],
|
21
|
+
top_pager: false,
|
22
|
+
bottom_pager: true,
|
23
|
+
remote: false,
|
24
|
+
min_search_length: 3,
|
25
|
+
id: false,
|
26
|
+
searcher: false,
|
27
|
+
needs_searcher: false,
|
28
|
+
live_search: false,
|
29
|
+
listeners: {},
|
30
|
+
collapse_empty_header: false,
|
31
|
+
collapse_empty_footer: false,
|
32
|
+
default_ajax_handler: true,
|
33
|
+
search_button: false,
|
34
|
+
searcher_size: nil,
|
42
35
|
}
|
43
36
|
|
44
37
|
def self.runtime_defaults
|
45
38
|
# run these lazily to catch any late I18n path changes
|
46
|
-
DEFAULTS.merge(
|
47
|
-
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
39
|
+
DEFAULTS.merge(Collection::DEFAULTS)
|
40
|
+
.merge(
|
41
|
+
if_empty: I18n.t("magic_grid.no_results").capitalize, # "No results found."
|
42
|
+
searcher_label: I18n.t("magic_grid.search.label").capitalize + ': ', # "Search: "
|
43
|
+
searcher_tooltip: I18n.t("magic_grid.search.tooltip"), # "type.. + <return>"
|
44
|
+
searcher_button: I18n.t("magic_grid.search.button").capitalize, # "Search"
|
51
45
|
)
|
52
46
|
end
|
53
47
|
|
54
|
-
def
|
48
|
+
def self.normalize_columns_options(cols_or_opts, opts)
|
55
49
|
if cols_or_opts.is_a? Hash
|
56
|
-
|
57
|
-
|
50
|
+
options = runtime_defaults.merge(cols_or_opts.reject {|k| k == :cols})
|
51
|
+
columns = cols_or_opts.fetch(:cols, [])
|
58
52
|
elsif cols_or_opts.is_a? Array
|
59
|
-
|
60
|
-
|
53
|
+
options = runtime_defaults.merge opts
|
54
|
+
columns = cols_or_opts
|
61
55
|
else
|
62
|
-
raise "I have no idea what that is, but it's not a
|
56
|
+
raise "I have no idea what that is, but it's not a columns list or options hash"
|
63
57
|
end
|
58
|
+
[options, columns]
|
59
|
+
end
|
60
|
+
|
61
|
+
def initialize(cols_or_opts, collection = nil, controller = nil, opts = {})
|
62
|
+
@options, @columns = *self.class.normalize_columns_options(cols_or_opts, opts)
|
64
63
|
@default_order = @options[:default_order]
|
65
64
|
@params = controller && controller.params || {}
|
66
|
-
@per_page = @options[:per_page]
|
67
|
-
@collection = Collection[collection, self]
|
68
|
-
begin
|
69
|
-
#if @collection.respond_to? :table
|
70
|
-
table_name = @collection.quoted_table_name
|
71
|
-
table_columns = @collection.column_names
|
72
|
-
rescue
|
73
|
-
msg = "Given collection doesn't respond to :quoted_table_name or :table well: "
|
74
|
-
MagicGrid.logger.debug("#{msg} - #{$!}")
|
75
|
-
table_name = nil
|
76
|
-
table_columns = @columns.each_index.to_a
|
77
|
-
end
|
78
|
-
i = 0
|
79
|
-
hash = []
|
80
|
-
@columns.map! do |c|
|
81
|
-
if c.is_a? Symbol
|
82
|
-
c = {:col => c}
|
83
|
-
elsif c.is_a? String
|
84
|
-
c = {:label => c}
|
85
|
-
end
|
86
|
-
c[:id] = i
|
87
|
-
i += 1
|
88
|
-
if c.key?(:col) and c[:col].is_a?(Symbol) and table_columns.include?(c[:col])
|
89
|
-
c[:sql] = "#{table_name}.#{@collection.quote_column_name(c[:col].to_s)}" unless c.key?(:sql)
|
90
|
-
end
|
91
|
-
c[:label] = c[:col].to_s.titleize if not c.key? :label
|
92
|
-
hash << c[:label]
|
93
|
-
c
|
94
|
-
end
|
95
|
-
if @options[:id]
|
96
|
-
@magic_id = @options[:id]
|
97
|
-
else
|
98
|
-
@magic_id = hash.join.hash.abs.to_s(36)
|
99
|
-
@magic_id << @collection.to_sql.hash.abs.to_s(36) if @collection.respond_to? :to_sql
|
100
|
-
end
|
101
|
-
@current_sort_col = sort_col_i = param(:col, @options[:default_col]).to_i
|
102
|
-
if @collection.sortable? and @columns.count > sort_col_i and @columns[sort_col_i].has_key?(:sql)
|
103
|
-
sort_col = @columns[sort_col_i][:sql]
|
104
|
-
@current_order = order(param(:order, @default_order))
|
105
|
-
sort_dir = order_sql(@current_order)
|
106
|
-
@collection.apply_sort(sort_col, sort_dir)
|
107
|
-
else
|
108
|
-
MagicGrid.logger.debug "#{self.class.name}: Ignoring sorting on non-AR collection"
|
109
|
-
end
|
110
65
|
|
111
|
-
|
112
|
-
if @options[:listener_handler].respond_to? :call
|
113
|
-
@collection.apply_filter_callback @options[:listener_handler]
|
114
|
-
else
|
115
|
-
@options[:listeners].each_pair do |key, value|
|
116
|
-
if @params[value] and not @params[value].to_s.empty?
|
117
|
-
@collection.apply_filter(value => @params[value])
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
else
|
122
|
-
unless @options[:listeners].empty?
|
123
|
-
MagicGrid.logger.warn "#{self.class.name}: Ignoring listener on dumb collection"
|
124
|
-
@options[:listeners] = {}
|
125
|
-
end
|
126
|
-
end
|
66
|
+
@collection = Collection.create_or_reuse collection, @options
|
127
67
|
|
128
|
-
@
|
129
|
-
|
130
|
-
|
131
|
-
if param(:q) and not param(:q).empty? and not @options[:searchable].empty?
|
132
|
-
@collection.apply_search(param(:q))
|
133
|
-
end
|
134
|
-
else
|
135
|
-
if not @options[:searchable].empty? or param(:q)
|
136
|
-
MagicGrid.logger.warn "#{self.class.name}: Ignoring searchable fields on non-AR collection"
|
137
|
-
end
|
138
|
-
@options[:searchable] = []
|
139
|
-
end
|
68
|
+
@columns = Column.columns_for_collection(@collection,
|
69
|
+
@columns,
|
70
|
+
@options[:searchable])
|
140
71
|
|
141
|
-
|
142
|
-
|
143
|
-
@
|
144
|
-
end
|
145
|
-
if @options[:post_filter] and @options[:post_filter].respond_to?(:call)
|
146
|
-
@collection.apply_filter_callback @options[:post_filter]
|
72
|
+
@current_sort_col = param(:col, @options[:default_col]).to_i
|
73
|
+
unless (0...@columns.count).cover? @current_sort_col
|
74
|
+
@current_sort_col = @options[:default_col]
|
147
75
|
end
|
148
|
-
|
149
|
-
@collection.
|
76
|
+
@current_order = order(param(:order, @default_order))
|
77
|
+
@collection.apply_sort(@columns[@current_sort_col], order_sql(@current_order))
|
78
|
+
|
79
|
+
filter_keys = @options[:listeners].values
|
80
|
+
filters = @params.slice(*filter_keys).reject {|k,v| v.to_s.empty? }
|
81
|
+
@collection.apply_filter filters
|
82
|
+
@collection.apply_pagination(current_page)
|
83
|
+
@collection.apply_search current_search
|
84
|
+
|
85
|
+
@collection.per_page = @options[:per_page]
|
86
|
+
@collection.apply_filter_callback @options[:listener_handler]
|
87
|
+
@collection.enable_post_filter @options[:collection_post_filter]
|
88
|
+
@collection.add_post_filter_callback @options[:post_filter]
|
89
|
+
end
|
90
|
+
|
91
|
+
def current_search
|
92
|
+
param(:q)
|
93
|
+
end
|
94
|
+
|
95
|
+
def magic_id
|
96
|
+
@options[:id] || (Column.hash_string(@columns) + @collection.hash_string)
|
150
97
|
end
|
151
98
|
|
152
99
|
def searchable?
|
153
|
-
@collection.searchable?
|
100
|
+
@collection.searchable?
|
154
101
|
end
|
155
102
|
|
156
103
|
def needs_searcher?
|
@@ -166,7 +113,7 @@ module MagicGrid
|
|
166
113
|
end
|
167
114
|
|
168
115
|
def param_key(key)
|
169
|
-
"#{
|
116
|
+
"#{magic_id}_#{key}".to_sym
|
170
117
|
end
|
171
118
|
|
172
119
|
def param(key, default=nil)
|
@@ -174,7 +121,7 @@ module MagicGrid
|
|
174
121
|
end
|
175
122
|
|
176
123
|
def base_params
|
177
|
-
@params.merge :
|
124
|
+
@params.merge magic_grid_id: magic_id
|
178
125
|
end
|
179
126
|
|
180
127
|
def current_page
|