magic_grid 0.12.3 → 0.12.4

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/Rakefile CHANGED
@@ -32,6 +32,6 @@ RSpec::Core::RakeTask.new(:spec) do |t|
32
32
  end
33
33
 
34
34
  desc "Run TestUnit and RSpec tests"
35
- task tests: [:spec, :test]
35
+ task :tests => [:spec, :test]
36
36
 
37
- task default: :tests
37
+ task :default => :tests
@@ -5,15 +5,15 @@ module MagicGrid
5
5
  class Collection
6
6
 
7
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
- count: nil,
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
+ :count => nil,
17
17
  }
18
18
 
19
19
  def initialize(collection, opts = {})
@@ -28,12 +28,14 @@ module MagicGrid
28
28
  @post_filter_callbacks = []
29
29
  @paginations = []
30
30
  @searchable_columns = []
31
+ @@kaminari_class = defined?(Kaminari) ? Kaminari : nil
31
32
  end
32
33
 
33
- delegate :quoted_table_name, :map, :count, to: :collection
34
+ delegate :quoted_table_name, :map, :count, :to => :collection
34
35
 
35
36
  attr_accessor :searchable_columns
36
37
  attr_reader :current_page, :original_count, :total_pages, :per_page, :searches
38
+ cattr_accessor :kaminari_class
37
39
 
38
40
  def options=(opts)
39
41
  @options = DEFAULTS.merge(opts || {})
@@ -85,7 +87,7 @@ module MagicGrid
85
87
  begin
86
88
  search_cols = searchable_columns.map {|c| c.custom_sql || c.name }
87
89
  clauses = search_cols.map {|c| c << " LIKE :search" }.join(" OR ")
88
- result = collection.where(clauses, {search: "%#{q}%"})
90
+ result = collection.where(clauses, {:search => "%#{q}%"})
89
91
  rescue
90
92
  MagicGrid.logger.debug "Given collection doesn't respond to :where well"
91
93
  end
@@ -181,7 +183,7 @@ module MagicGrid
181
183
  @original_count = self.count @collection
182
184
  @per_page = n
183
185
  if @per_page
184
- @total_pages = @original_count / @per_page
186
+ @total_pages = calculate_total_pages(@per_page, @original_count)
185
187
  else
186
188
  @total_pages = 1
187
189
  end
@@ -213,13 +215,13 @@ module MagicGrid
213
215
  total_entries)
214
216
 
215
217
  if collection.respond_to? :paginate
216
- collection.paginate(page: @current_page,
217
- per_page: @per_page,
218
- total_entries: total_entries)
218
+ collection.paginate(:page => @current_page,
219
+ :per_page => @per_page,
220
+ :total_entries => total_entries)
219
221
  elsif collection.respond_to? :page
220
222
  collection.page(@current_page).per(@per_page)
221
- elsif collection.is_a?(Array) and Module.const_defined?(:Kaminari)
222
- Kaminari.paginate_array(collection).page(@current_page).per(@per_page)
223
+ elsif collection.is_a?(Array) and @@kaminari_class
224
+ @@kaminari_class.paginate_array(collection).page(@current_page).per(@per_page)
223
225
  else
224
226
  default_paginate(collection, @current_page, @per_page)
225
227
  end
@@ -256,16 +258,26 @@ module MagicGrid
256
258
  @reduced_collection ||= apply_all_operations(@collection)
257
259
  end
258
260
 
259
- private
261
+ def calculate_total_pages(per_page, total_entries)
262
+ pages = total_entries / per_page
263
+ pages += 1 if total_entries % per_page > 0
264
+ if pages < 1
265
+ 1
266
+ else
267
+ pages
268
+ end
269
+ end
260
270
 
261
271
  def bound_current_page(page, per_page, total_entries)
262
- pages = total_entries / per_page
263
- pages = 1 if pages == 0
264
- if page > pages
272
+ pages = calculate_total_pages(per_page, total_entries)
273
+ if page < 1
274
+ 1
275
+ elsif page > pages
265
276
  pages
266
277
  else
267
278
  page
268
279
  end
269
280
  end
281
+
270
282
  end
271
283
  end
@@ -2,7 +2,7 @@ module MagicGrid
2
2
  class Column
3
3
 
4
4
  def self.columns_for_collection(collection, columns, searchables)
5
- columns.map.each_with_index { |c, i|
5
+ columns.each_with_index.map { |c, i|
6
6
  MagicGrid::Column.new(collection, c, i)
7
7
  }.tap do |cols|
8
8
  if searchables == false
@@ -68,9 +68,9 @@ module MagicGrid
68
68
  @collection = collection
69
69
  @col = case c
70
70
  when Symbol
71
- {col: c}
71
+ {:col => c}
72
72
  when String
73
- {label: c}
73
+ {:label => c}
74
74
  else
75
75
  c
76
76
  end
@@ -17,31 +17,30 @@ module MagicGrid
17
17
  end
18
18
 
19
19
  DEFAULTS = {
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,
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,
35
35
  }
36
36
 
37
37
  def self.runtime_defaults
38
38
  # run these lazily to catch any late I18n path changes
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"
39
+ DEFAULTS.merge(Collection::DEFAULTS).merge(
40
+ :if_empty => I18n.t("magic_grid.no_results").capitalize, # "No results found."
41
+ :searcher_label => I18n.t("magic_grid.search.label").capitalize + ': ', # "Search: "
42
+ :searcher_tooltip => I18n.t("magic_grid.search.tooltip"), # "type.. + <return>"
43
+ :searcher_button => I18n.t("magic_grid.search.button").capitalize # "Search"
45
44
  )
46
45
  end
47
46
 
@@ -121,7 +120,7 @@ module MagicGrid
121
120
  end
122
121
 
123
122
  def base_params
124
- @params.merge magic_grid_id: magic_id
123
+ @params.merge :magic_grid_id => magic_id
125
124
  end
126
125
 
127
126
  def current_page
@@ -16,18 +16,18 @@ module MagicGrid
16
16
  def render(&row_renderer)
17
17
  @spinner_drawn = false
18
18
  grid_data = {
19
- searcher: @grid.searcher,
20
- current: @current_url,
21
- live_search: @grid.options[:live_search],
22
- listeners: @grid.options[:listeners],
23
- remote: @grid.options[:remote],
24
- default_ajax_handler: @grid.options[:default_ajax_handler],
25
- params: @grid.base_params,
19
+ :searcher => @grid.searcher,
20
+ :current => @current_url,
21
+ :live_search => @grid.options[:live_search],
22
+ :listeners => @grid.options[:listeners],
23
+ :remote => @grid.options[:remote],
24
+ :default_ajax_handler => @grid.options[:default_ajax_handler],
25
+ :params => @grid.base_params,
26
26
  }
27
27
  table_options = {
28
- class: (['magic_grid'] << @grid.options[:class]).join(' '),
29
- id: @grid.magic_id,
30
- data: grid_data.select {|_,v| v }
28
+ :class => (['magic_grid'] << @grid.options[:class]).join(' '),
29
+ :id => @grid.magic_id,
30
+ :data => grid_data.select {|_,v| v }
31
31
  }
32
32
  @view.content_tag('table', table_options) do
33
33
  thead + tbody(&row_renderer) + tfoot
@@ -35,13 +35,13 @@ module MagicGrid
35
35
  end
36
36
 
37
37
  def thead
38
- @view.content_tag('thead', data: {params: @grid.base_params}) do
38
+ @view.content_tag('thead', :data => {:params => @grid.base_params}) do
39
39
  magic_grid_head
40
40
  end
41
41
  end
42
42
 
43
43
  def tbody(&row_renderer)
44
- @view.content_tag('tbody', class: "ui-widget-content") do
44
+ @view.content_tag('tbody', :class => "ui-widget-content") do
45
45
  magic_rows &row_renderer
46
46
  end
47
47
  end
@@ -56,8 +56,8 @@ module MagicGrid
56
56
  unless @spinner_drawn
57
57
  @spinner_drawn = true
58
58
  @view.tag('span',
59
- id: (@grid.magic_id.to_s + "_spinner"),
60
- class: "magic_grid_spinner")
59
+ :id => (@grid.magic_id.to_s + "_spinner"),
60
+ :class => "magic_grid_spinner")
61
61
  end
62
62
  end
63
63
 
@@ -88,8 +88,8 @@ module MagicGrid
88
88
  def filler_block(content = nil, &block)
89
89
  @view.content_tag 'tr' do
90
90
  @view.content_tag('td', content,
91
- class: 'full-width ui-widget-header',
92
- colspan: @grid.columns.count,
91
+ :class => 'full-width ui-widget-header',
92
+ :colspan => @grid.columns.count,
93
93
  &block)
94
94
  end
95
95
  end
@@ -102,7 +102,7 @@ module MagicGrid
102
102
  if col.sortable?
103
103
  sortable_header(col)
104
104
  else
105
- @view.content_tag 'th', col.label.html_safe, class: classes.join(' ')
105
+ @view.content_tag 'th', col.label.html_safe, :class => classes.join(' ')
106
106
  end
107
107
  end
108
108
  end
@@ -119,8 +119,8 @@ module MagicGrid
119
119
  def render_empty_collection(fallback)
120
120
  if fallback
121
121
  @view.content_tag 'tr' do
122
- @view.content_tag('td', colspan: @grid.columns.count,
123
- class: 'if-empty') do
122
+ @view.content_tag('td', :colspan => @grid.columns.count,
123
+ :class => 'if-empty') do
124
124
  if fallback.respond_to? :call
125
125
  fallback.call(@grid).to_s
126
126
  else
@@ -135,14 +135,14 @@ module MagicGrid
135
135
  if row_renderer
136
136
  @view.capture(record, &row_renderer)
137
137
  else
138
- @view.content_tag 'tr', class: @view.cycle('odd', 'even') do
138
+ @view.content_tag 'tr', :class => @view.cycle('odd', 'even') do
139
139
  @grid.columns.map { |c| grid_cell(c, record) }.join.html_safe
140
140
  end
141
141
  end
142
142
  end
143
143
 
144
144
  def grid_cell(column, record)
145
- @view.content_tag('td', class: column.html_classes) do
145
+ @view.content_tag('td', :class => column.html_classes) do
146
146
  method = column.reader
147
147
  if method.respond_to? :call
148
148
  method.call(record).to_s
@@ -163,7 +163,7 @@ module MagicGrid
163
163
  end
164
164
 
165
165
  def order_icon(order = -1)
166
- @view.content_tag 'span', '', class: "ui-icon #{order_icon_class(order)}"
166
+ @view.content_tag 'span', '', :class => "ui-icon #{order_icon_class(order)}"
167
167
  end
168
168
 
169
169
  def order_icon_class(order = -1)
@@ -202,8 +202,8 @@ module MagicGrid
202
202
  if column_link_params[@grid.param_key(:order)].to_i == default_sort_order.to_i
203
203
  column_link_params.delete(@grid.param_key(:order))
204
204
  end
205
- @view.content_tag 'th', class: classes.join(' ') do
206
- @view.link_to column_link_params, remote: @grid.options[:remote] do
205
+ @view.content_tag 'th', :class => classes.join(' ') do
206
+ @view.link_to column_link_params, :remote => @grid.options[:remote] do
207
207
  label.html_safe << order_icon(order)
208
208
  end
209
209
  end
@@ -211,8 +211,8 @@ module MagicGrid
211
211
 
212
212
  def searcher_block(&spinner)
213
213
  @view.content_tag('tr') do
214
- @view.content_tag('td', class: 'searcher full-width ui-widget-header',
215
- colspan: @grid.columns.count) do
214
+ @view.content_tag('td', :class => 'searcher full-width ui-widget-header',
215
+ :colspan => @grid.columns.count) do
216
216
  searcher_input(&spinner)
217
217
  end
218
218
  end
@@ -220,20 +220,20 @@ module MagicGrid
220
220
 
221
221
  def searcher_input(&spinner)
222
222
  searcher_data = {
223
- min_length: @grid.options[:min_search_length],
224
- current: @grid.current_search || "",
223
+ :min_length => @grid.options[:min_search_length],
224
+ :current => @grid.current_search || "",
225
225
  }
226
226
  searcher = @view.label_tag(@grid.searcher.to_sym,
227
227
  @grid.options[:searcher_label])
228
228
  searcher << @view.search_field_tag(@grid.searcher.to_sym,
229
229
  @grid.param(:q),
230
- placeholder: @grid.options[:searcher_tooltip],
231
- size: @grid.options[:searcher_size],
232
- data: searcher_data,
233
- form: "a form that doesn't exist")
230
+ :placeholder => @grid.options[:searcher_tooltip],
231
+ :size => @grid.options[:searcher_size],
232
+ :data => searcher_data,
233
+ :form => "a form that doesn't exist")
234
234
  if @grid.options[:search_button]
235
235
  searcher << @view.button_tag(@grid.options[:searcher_button],
236
- class: 'magic-grid-search-button')
236
+ :class => 'magic-grid-search-button')
237
237
  end
238
238
  searcher << yield if block_given?
239
239
  searcher
@@ -254,11 +254,11 @@ module MagicGrid
254
254
 
255
255
  def magic_pager_block(&spinner)
256
256
  @view.content_tag('tr') do
257
- @view.content_tag('td', class: 'full-width ui-widget-header magic-pager',
258
- colspan: @grid.columns.count) do
257
+ @view.content_tag('td', :class => 'full-width ui-widget-header magic-pager',
258
+ :colspan => @grid.columns.count) do
259
259
  pager = magic_pager(@grid.magic_collection,
260
- param_name: @grid.param_key(:page),
261
- params: @grid.base_params
260
+ :param_name => @grid.param_key(:page),
261
+ :params => @grid.base_params
262
262
  )
263
263
  if spinner
264
264
  pager << @view.capture(&spinner)
@@ -1,3 +1,3 @@
1
1
  module MagicGrid
2
- VERSION = "0.12.3"
2
+ VERSION = "0.12.4"
3
3
  end
@@ -95,16 +95,88 @@ describe MagicGrid::Collection do
95
95
  end
96
96
  end
97
97
 
98
+ describe "pagination" do
99
+ context "#calculate_total_pages" do
100
+ let(:array) { Array.new(10) { 1 } }
101
+ subject { MagicGrid::Collection.new(array, nil) }
102
+ it "should round correctly" do
103
+ subject.calculate_total_pages(2, 10).should == 5
104
+ subject.calculate_total_pages(3, 10).should == 4
105
+ subject.calculate_total_pages(4, 10).should == 3
106
+ end
107
+ end
108
+
109
+ context "#bound_current_page" do
110
+ let(:array) { Array.new(10) { 1 } }
111
+ subject { MagicGrid::Collection.new(array, nil) }
112
+
113
+ it "should round page 0 correctly" do
114
+ subject.bound_current_page(0, 2, 10).should == 1
115
+ subject.bound_current_page(0, 3, 10).should == 1
116
+ subject.bound_current_page(0, 4, 10).should == 1
117
+ end
118
+
119
+ it "should round page > pages correctly" do
120
+ subject.bound_current_page(10, 2, 10).should == 5
121
+ subject.bound_current_page(10, 3, 10).should == 4
122
+ subject.bound_current_page(10, 4, 10).should == 3
123
+ end
124
+ end
125
+ end
126
+
127
+ describe "#perform_pagination" do
128
+
129
+ context "page counts" do
130
+ let(:array) { Array.new(100) { 1 } }
131
+ subject { MagicGrid::Collection.new(array, nil) }
132
+
133
+ it "should correctly calculate uneven page splits" do
134
+ subject.per_page = 33
135
+ subject.total_pages.should == 4
136
+ end
137
+
138
+ it "should correctly calculate even page splits" do
139
+ subject.per_page = 20
140
+ subject.total_pages.should == 5
141
+ end
142
+ end
143
+
144
+ context "page bounds checks" do
145
+ let(:array) { (1..10).to_a }
146
+ subject { MagicGrid::Collection.new(array, nil) }
147
+
148
+ it "should round down to the last page if a later page is requested" do
149
+ subject.per_page = 3
150
+ subject.total_pages.should == 4
151
+ subject.apply_pagination(5).perform_pagination(array)
152
+ subject.current_page.should == 4
153
+ end
154
+
155
+ context "providing the correct data" do
156
+ before(:each) { subject.per_page = 3 }
157
+ it "handles pages beyond lower bound" do
158
+ subject.apply_pagination(0).perform_pagination(array).should == [1,2,3]
159
+ end
160
+ it "handles pages in bounds" do
161
+ subject.apply_pagination(1).perform_pagination(array).should == [1,2,3]
162
+ subject.apply_pagination(2).perform_pagination(array).should == [4,5,6]
163
+ subject.apply_pagination(3).perform_pagination(array).should == [7,8,9]
164
+ subject.apply_pagination(4).perform_pagination(array).should == [10]
165
+ end
166
+ it "handles pages above bounds" do
167
+ subject.apply_pagination(5).perform_pagination(array).should == [10]
168
+ end
169
+ end
170
+ end
171
+
98
172
  #TODO these tests will only really work properly once we have the ability
99
173
  # to undefine constants, which looks like it should be coming in a future
100
174
  # version of RSpec (as in post 2.11.1)
101
175
 
102
- describe "#perform_pagination" do
103
-
104
176
  context "when #paginate (aka WillPaginate) is available" do
105
177
  it "should call paginate helper when it is detected" do
106
178
  array = [1].tap do |a|
107
- a.should_receive(:paginate).with(page: 1, per_page: 1, total_entries: 1) { a }
179
+ a.should_receive(:paginate).with(:page => 1, :per_page => 1, :total_entries => 1) { a }
108
180
  end
109
181
  collection = MagicGrid::Collection.new(array, nil)
110
182
  collection.per_page = 1
@@ -113,7 +185,7 @@ describe MagicGrid::Collection do
113
185
  end
114
186
  end
115
187
 
116
- unless Module.const_defined? :WillPaginate
188
+ unless $will_paginate
117
189
  context "when #page (possibly from Kaminari) is available" do
118
190
  it "should call paginate helper when it is detected" do
119
191
  array = [1].tap do |a|
@@ -127,21 +199,25 @@ describe MagicGrid::Collection do
127
199
  end
128
200
  end
129
201
 
130
- context "when given an Array and Kaminari is available" do
131
- it "should call paginate helper when it is detected" do
132
- array = Array.new(10) { 1 }
133
- kaminaried_array = [1,1].tap do |ka|
134
- ka.should_receive(:per).with(1) { ka }
135
- ka.should_receive(:page).with(1) { ka }
202
+ unless $kaminari
203
+ context "when given an Array and Kaminari is available" do
204
+ it "should call paginate helper when it is detected" do
205
+ array = Array.new(10) { 1 }
206
+ kaminaried_array = [1].tap do |ka|
207
+ ka.should_receive(:per).with(1) { ka }
208
+ ka.should_receive(:page).with(1) { ka }
209
+ end
210
+ kaminari = double.tap do |k|
211
+ k.should_receive(:paginate_array).with(array) { kaminaried_array }
212
+ end
213
+ collection = MagicGrid::Collection.new(array, nil)
214
+ collection.per_page = 1
215
+ collection.apply_pagination 1
216
+ old_kaminari = MagicGrid::Collection.kaminari_class
217
+ MagicGrid::Collection.kaminari_class = kaminari
218
+ collection.perform_pagination(array).should == kaminaried_array
219
+ MagicGrid::Collection.kaminari_class = old_kaminari
136
220
  end
137
- kaminari = double.tap do |k|
138
- k.should_receive(:paginate_array).with(array) { kaminaried_array }
139
- end
140
- stub_const('Kaminari', kaminari)
141
- collection = MagicGrid::Collection.new(array, nil)
142
- collection.per_page = 1
143
- collection.apply_pagination 1
144
- collection.perform_pagination(array).should == kaminaried_array
145
221
  end
146
222
  end
147
223
  end
@@ -149,7 +225,7 @@ describe MagicGrid::Collection do
149
225
  context "when no pagination is provided" do
150
226
  # TODO replace this when rspec-mocks add 'hide_const'
151
227
  # before :each do
152
- # if Module.const_defined?(:Kaminari)
228
+ # if defined?(Kaminari)
153
229
  # @kaminari = Module.const_get(:Kaminari)
154
230
  # Object.send(:remove_const, :Kaminari)
155
231
  # end