magic_grid 0.11.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
[](http://travis-ci.org/rmg/magic_grid)
|
5
|
+
[](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
|