magic_grid 0.12.3 → 0.12.4

Sign up to get free protection for your applications and to get access to all the features.
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