gitter 1.1.3
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/.gitignore +5 -0
- data/.travis.yml +6 -0
- data/Gemfile +14 -0
- data/Guardfile +21 -0
- data/License +20 -0
- data/Rakefile +9 -0
- data/Readme.markdown +159 -0
- data/assets/images/sort_asc.gif +0 -0
- data/assets/images/sort_desc.gif +0 -0
- data/gitter.gemspec +28 -0
- data/lib/gitter.rb +13 -0
- data/lib/gitter/axis.rb +48 -0
- data/lib/gitter/base.rb +149 -0
- data/lib/gitter/breadcrumbs.rb +44 -0
- data/lib/gitter/cell.rb +11 -0
- data/lib/gitter/column.rb +142 -0
- data/lib/gitter/columns.rb +110 -0
- data/lib/gitter/controller.rb +19 -0
- data/lib/gitter/csv.rb +9 -0
- data/lib/gitter/driver.rb +26 -0
- data/lib/gitter/drivers/abstract_driver.rb +36 -0
- data/lib/gitter/drivers/active_record_driver.rb +84 -0
- data/lib/gitter/facet.rb +95 -0
- data/lib/gitter/filters.rb +4 -0
- data/lib/gitter/filters/abstract_filter.rb +94 -0
- data/lib/gitter/filters/block_filter.rb +16 -0
- data/lib/gitter/filters/column_filter.rb +50 -0
- data/lib/gitter/filters/select_filter.rb +43 -0
- data/lib/gitter/grid.rb +23 -0
- data/lib/gitter/header.rb +44 -0
- data/lib/gitter/helpers.rb +44 -0
- data/lib/gitter/i18n.rb +11 -0
- data/lib/gitter/model.rb +40 -0
- data/lib/gitter/pivot.rb +107 -0
- data/lib/gitter/pivot_grid.rb +23 -0
- data/lib/gitter/railtie.rb +8 -0
- data/lib/gitter/table.rb +149 -0
- data/lib/gitter/utils.rb +12 -0
- data/lib/gitter/version.rb +3 -0
- data/spec/breadcrumbs_spec.rb +24 -0
- data/spec/column_filter_spec.rb +80 -0
- data/spec/column_spec.rb +159 -0
- data/spec/facets_spec.rb +75 -0
- data/spec/grid_spec.rb +92 -0
- data/spec/helper_spec.rb +8 -0
- data/spec/i18n_spec.rb +39 -0
- data/spec/inputs_spec.rb +0 -0
- data/spec/locales/de.yml +10 -0
- data/spec/locales/en.yml +10 -0
- data/spec/range_filter_spec.rb +32 -0
- data/spec/scope_filter_spec.rb +12 -0
- data/spec/select_filter_spec.rb +22 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/support/database.rb +24 -0
- data/spec/support/person_grid.rb +71 -0
- metadata +152 -0
data/lib/gitter/pivot.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
module Gitter
|
2
|
+
|
3
|
+
module Pivot
|
4
|
+
|
5
|
+
def pivot_cells *groups
|
6
|
+
opts = groups.extract_options!
|
7
|
+
sum = opts[:sum]
|
8
|
+
count = opts[:count]; count = :id if count == true
|
9
|
+
|
10
|
+
groups = [groups].flatten
|
11
|
+
|
12
|
+
cells = self.scope
|
13
|
+
groups.each{ |g| cells = cells.group(g)}
|
14
|
+
cells = cells.sum(sum) if sum
|
15
|
+
cells = cells.count(:id) if count
|
16
|
+
cells
|
17
|
+
end
|
18
|
+
|
19
|
+
def x_axis *args
|
20
|
+
if args.present?
|
21
|
+
@x_axis = Axis.new self, *args
|
22
|
+
else
|
23
|
+
@x_axis or raise ConfigurationError, 'undefined x_axis'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def y_axis *args
|
28
|
+
if args.present?
|
29
|
+
@y_axis = Axis.new self, *args
|
30
|
+
else
|
31
|
+
@y_axis or raise ConfigurationError, 'undefined y_axis'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def cell &cell
|
36
|
+
if cell
|
37
|
+
@cell ||= cell
|
38
|
+
else
|
39
|
+
@cell or raise ConfigurationError, 'undefined cell'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def drill_down *names
|
44
|
+
if names.present?
|
45
|
+
@drill_down ||= facet_for names
|
46
|
+
else
|
47
|
+
@drill_down ||= @filters.keys
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def input_tags
|
52
|
+
[]
|
53
|
+
end
|
54
|
+
|
55
|
+
def columns
|
56
|
+
@columns ||= x_axis.titles.map{|x|Column.new self, x}
|
57
|
+
end
|
58
|
+
|
59
|
+
def header_rows
|
60
|
+
@header_rows ||= begin
|
61
|
+
row = [''] + x_axis.titles
|
62
|
+
row = row.map{|h|Gitter::Header.new self, h}
|
63
|
+
[row]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def rows scope = self.scope
|
68
|
+
y_axis.data_titles.map do |y,y_title|
|
69
|
+
row = []
|
70
|
+
row << Gitter::Cell.new(y_title)
|
71
|
+
row += x_axis.data.map do |x|
|
72
|
+
content = cell.call data_scope, x, y
|
73
|
+
Gitter::Cell.new content
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# returns [ down, current, ups ]
|
79
|
+
def drill_down_facets
|
80
|
+
drill = drill_down.reverse
|
81
|
+
i = drill.find_index{|f|f.selected?}
|
82
|
+
if i == 0
|
83
|
+
down = nil
|
84
|
+
current, *ups = drill[0..-1]
|
85
|
+
else
|
86
|
+
down, current, *ups = drill[i-1..-1]
|
87
|
+
end
|
88
|
+
|
89
|
+
[ down, current, ups ]
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def data_scope
|
94
|
+
@data_scope ||= scope.group(x_axis.attr).group(y_axis.attr)
|
95
|
+
end
|
96
|
+
|
97
|
+
def facet_for arg
|
98
|
+
if arg.respond_to? :map
|
99
|
+
arg.map{|a|facet_for a}
|
100
|
+
else
|
101
|
+
filter = @filters[arg] or raise ConfigurationError, "unknown filter #{arg}"
|
102
|
+
Facet.new filter
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'gitter/driver'
|
2
|
+
require 'gitter/base'
|
3
|
+
require 'gitter/pivot'
|
4
|
+
require 'gitter/breadcrumbs'
|
5
|
+
require 'gitter/csv'
|
6
|
+
require 'gitter/i18n'
|
7
|
+
require 'gitter/helpers'
|
8
|
+
require 'gitter/model'
|
9
|
+
|
10
|
+
module Gitter
|
11
|
+
|
12
|
+
class PivotGrid
|
13
|
+
include Gitter::Base
|
14
|
+
include Gitter::Driver
|
15
|
+
include Gitter::Pivot
|
16
|
+
include Gitter::Breadcrumbs
|
17
|
+
include Gitter::CSV
|
18
|
+
include Gitter::I18n
|
19
|
+
include Gitter::Helpers
|
20
|
+
include Gitter::Model
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/gitter/table.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
|
3
|
+
module Gitter
|
4
|
+
|
5
|
+
class TableCell
|
6
|
+
include ActionView::Helpers::NumberHelper
|
7
|
+
|
8
|
+
|
9
|
+
attr_reader :x, :y, :content
|
10
|
+
|
11
|
+
def initialize x, y, content
|
12
|
+
@x, @y, @content = x, y, content
|
13
|
+
end
|
14
|
+
|
15
|
+
def html opts = {}
|
16
|
+
Table.tag :td, formatted_content, opts.merge(class: "#{x} #{y}")
|
17
|
+
end
|
18
|
+
|
19
|
+
def header?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
def formatted_content
|
24
|
+
number_with_delimiter content, delimiter: '.'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class TableHeaderCell < TableCell
|
29
|
+
attr_reader :content
|
30
|
+
|
31
|
+
def initialize content
|
32
|
+
@content = content
|
33
|
+
end
|
34
|
+
|
35
|
+
def html opts = {}
|
36
|
+
Table.tag :th, formatted_content, opts
|
37
|
+
end
|
38
|
+
|
39
|
+
def header?
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def formatted_content
|
44
|
+
content
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class Table
|
50
|
+
extend ActionView::Helpers::TagHelper
|
51
|
+
extend ActionView::Helpers::OutputSafetyHelper
|
52
|
+
|
53
|
+
def self.tag tag, content, opts = {}
|
54
|
+
opts = opts.merge(class: "#{opts[:class]} grid pivot")
|
55
|
+
content_tag tag, raw(content), opts
|
56
|
+
end
|
57
|
+
|
58
|
+
attr_reader :title, :x_axis, :y_axis, :data, :opts
|
59
|
+
|
60
|
+
# axis: responds to each, yielding [key,title] or key
|
61
|
+
# # data: hash from [x_key,y_key] to cell_array
|
62
|
+
def initialize title, x_axis, y_axis, data, opts = {}
|
63
|
+
@title, @x_axis, @y_axis, @data, @opts = title, x_axis, y_axis, data, opts
|
64
|
+
@cells = data.dup
|
65
|
+
if label = opts[:show_sums]
|
66
|
+
add_sums
|
67
|
+
@x_axis = add_sum_label_to_axis @x_axis, label
|
68
|
+
@y_axis = add_sum_label_to_axis @y_axis, label
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def empty?
|
73
|
+
data.empty?
|
74
|
+
end
|
75
|
+
|
76
|
+
def rows
|
77
|
+
@rows ||= begin
|
78
|
+
rows = []
|
79
|
+
rows << x_header if x_header
|
80
|
+
|
81
|
+
rows + (y_axis||[nil]).map do |y,y_title|
|
82
|
+
row = (x_axis||[nil]).map do |x,x_title|
|
83
|
+
cell = @cells[cell_key(x,y)]
|
84
|
+
cell = yield cell, x, y if block_given?
|
85
|
+
TableCell.new x, y, cell
|
86
|
+
end
|
87
|
+
row.unshift TableHeaderCell.new(y_title||y) if y_axis
|
88
|
+
row
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def html
|
94
|
+
@html ||= begin
|
95
|
+
h = rows.map do |row|
|
96
|
+
Table.tag :tr, (row.map{|cell| cell.html} * "\n")
|
97
|
+
end * "\n"
|
98
|
+
Table.tag :table, h
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def x_header
|
105
|
+
@x_header ||= begin
|
106
|
+
if x_axis
|
107
|
+
h = x_axis.map{|key,title| TableHeaderCell.new(title||key) }
|
108
|
+
h.unshift TableHeaderCell.new('') if y_axis
|
109
|
+
h
|
110
|
+
else
|
111
|
+
nil
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def cell_key x, y
|
117
|
+
if x.nil? || y.nil?
|
118
|
+
x.nil? ? y : x
|
119
|
+
else
|
120
|
+
[x,y]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_sums
|
125
|
+
xsums, ysums = {}, {}
|
126
|
+
sum = 0
|
127
|
+
@cells.each do |key,value|
|
128
|
+
x, y = *key
|
129
|
+
xsums[y] = (xsums[y]||0) + value
|
130
|
+
ysums[x] = (ysums[x]||0) + value
|
131
|
+
sum += value
|
132
|
+
end
|
133
|
+
xsums.each{|y,sum| @cells[cell_key(:sum,y)] = sum}
|
134
|
+
ysums.each{|x,sum| @cells[cell_key(x,:sum)] = sum}
|
135
|
+
@cells[[:sum,:sum]] = sum
|
136
|
+
@cells
|
137
|
+
end
|
138
|
+
|
139
|
+
def add_sum_label_to_axis axis, label = nil
|
140
|
+
label = 'Sum' unless String === label
|
141
|
+
case axis
|
142
|
+
when Array then axis + [[:sum, label]]
|
143
|
+
when Hash then axis.merge(:sum => label)
|
144
|
+
else nil;
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
data/lib/gitter/utils.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Gitter
|
4
|
+
|
5
|
+
describe Grid do
|
6
|
+
|
7
|
+
it 'should handle one breadcrumb' do
|
8
|
+
g = PersonGrid.new :name => 'bla'
|
9
|
+
g.breadcrumbs.should == { 'Name' => 'bla' }
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should handle breadcrumb with label' do
|
13
|
+
g = PersonGrid.new :name3 => 'bla'
|
14
|
+
g.breadcrumbs.should == { 'Three' => 'bla' }
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should handle many breadcrumbs' do
|
18
|
+
g = PersonGrid.new :name => 'Mike', :surname => 'Miller'
|
19
|
+
g.breadcrumbs.should == { 'Name' => 'Mike', 'Surname' => 'Miller' }
|
20
|
+
|
21
|
+
g = PersonGrid.new :surname => 'Miller', :name => 'Mike'
|
22
|
+
g.breadcrumbs.should == { 'Surname' => 'Miller', 'Name' => 'Mike' }
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Persons
|
4
|
+
|
5
|
+
describe Gitter do
|
6
|
+
|
7
|
+
context 'column filter' do
|
8
|
+
check_include Max, :name => 'Max'
|
9
|
+
check_include Lisa, :surname => 'Adult'
|
10
|
+
check_include John, Dana, :surname => 'Twen'
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'column filter with :column' do
|
14
|
+
check_include Max, :name2 => 'Max'
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'column filter with instance ignore_case' do
|
18
|
+
check_include [], :name => 'max'
|
19
|
+
check_include [], :name => 'max', :ignore_case => false
|
20
|
+
check_include Max, :name => 'max', :ignore_case => true
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'column filter with instance inexact' do
|
24
|
+
check_include [], :name => 'ax'
|
25
|
+
check_include [], :name => 'ax', :exact => true
|
26
|
+
check_include Max, :name => 'ax', :exact => false
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'column filter with many columns' do
|
30
|
+
check_include Max, :any_name => 'Max'
|
31
|
+
check_include Max, :any_name => 'Kid'
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'column filter with many columns with ignore_case' do
|
35
|
+
check_include [], :any_name => 'max'
|
36
|
+
check_include [], :any_name => 'ax', :exact => true
|
37
|
+
check_include Max, :any_name => 'ax', :exact => false
|
38
|
+
check_include [], :any_name => 'id'
|
39
|
+
check_include [], :any_name => 'id', :exact => true
|
40
|
+
check_include Max, :any_name => 'id', :exact => false
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'column filter with many columns with inexact' do
|
44
|
+
check_include [], :any_name => 'max'
|
45
|
+
check_include [], :any_name => 'max', :ignore_case => false
|
46
|
+
check_include Max, :any_name => 'max', :ignore_case => true
|
47
|
+
check_include [], :any_name => 'kid'
|
48
|
+
check_include [], :any_name => 'kid', :ignore_case => false
|
49
|
+
check_include Max, :any_name => 'kid', :ignore_case => true
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'column filter with ignore_case' do
|
53
|
+
check_include Max, :name_ignore => 'max'
|
54
|
+
check_include Max, :name_ignore => 'Max'
|
55
|
+
|
56
|
+
check_include [], :name_ignore => 'max', :ignore_case => false
|
57
|
+
check_include Max, :name_ignore => 'Max', :ignore_case => false
|
58
|
+
|
59
|
+
check_include Max, :name_ignore => 'max', :ignore_case => true
|
60
|
+
check_include Max, :name_ignore => 'Max', :ignore_case => true
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'column filter with instance inexact' do
|
64
|
+
check_include Max, :name_inexact => 'ax'
|
65
|
+
check_include Max, :name_inexact => 'Max'
|
66
|
+
|
67
|
+
check_include [], :name_inexact => 'ax', :exact => true
|
68
|
+
check_include Max, :name_inexact => 'Max', :exact => true
|
69
|
+
|
70
|
+
check_include Max, :name_inexact => 'ax', :exact => false
|
71
|
+
check_include Max, :name_inexact => 'Max', :exact => false
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'search' do
|
75
|
+
check_include Max, :search_name => 'Max'
|
76
|
+
check_include Max, :search_name => 'max'
|
77
|
+
check_include Max, :search_name => 'ax'
|
78
|
+
check_include [], :search_name => 'Kid'
|
79
|
+
end
|
80
|
+
end
|
data/spec/column_spec.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Gitter
|
4
|
+
|
5
|
+
describe Column do
|
6
|
+
it 'should have name and header' do
|
7
|
+
g = PersonGrid.new
|
8
|
+
col_spec = g.columns.detect_name :name
|
9
|
+
col_spec.name.should == :name
|
10
|
+
|
11
|
+
col= g.columns.detect_name :name
|
12
|
+
col.name.should == :name
|
13
|
+
col.header.should == 'Name'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should have settable header' do
|
17
|
+
g = PersonGrid.new
|
18
|
+
col_spec = g.columns.detect_name :full_name
|
19
|
+
col_spec.name.should == :full_name
|
20
|
+
|
21
|
+
col = g.columns.detect_name :full_name
|
22
|
+
col.name.should == :full_name
|
23
|
+
col.header.should == 'Full name'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should have a ColumnSpec' do
|
27
|
+
g = PersonGrid.new
|
28
|
+
col= g.columns.detect_name :name
|
29
|
+
col.spec.class.should == ColumnSpec
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should have settable attribute' do
|
33
|
+
class Foo < Gitter::Grid
|
34
|
+
scope do Person.scoped end
|
35
|
+
column :name1, :column => :name
|
36
|
+
end
|
37
|
+
g = Foo.new
|
38
|
+
col_spec = g.columns.detect_name :name1
|
39
|
+
col_spec.name.should == :name1
|
40
|
+
|
41
|
+
col = g.columns.detect_name :name1
|
42
|
+
col.name.should == :name1
|
43
|
+
col.header.should == 'Name1'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should have headers' do
|
47
|
+
g = PersonGrid.new
|
48
|
+
g.headers.should == [ 'Name', 'Full name', 'Job Title' ]
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should have rows' do
|
52
|
+
g = PersonGrid.new
|
53
|
+
g.rows.size.should == 7
|
54
|
+
|
55
|
+
g = PersonGrid.new :order => :name
|
56
|
+
g.rows.size.should == 7
|
57
|
+
g.rows.should == [
|
58
|
+
["Dana", "Dana Twen", "teacher"],
|
59
|
+
["Dick", "Dick Teeny", "student"],
|
60
|
+
["Joe", "Joe Teen", "student"],
|
61
|
+
["John", "John Twen", "teacher"],
|
62
|
+
["Lisa", "Lisa Adult", "dentist"],
|
63
|
+
["Max", "Max Kid", "student"],
|
64
|
+
["Tina", "Tina Child", "student"]
|
65
|
+
]
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should order columns' do
|
69
|
+
g = PersonGrid.new :order => :profession
|
70
|
+
g.rows.size.should == 7
|
71
|
+
g.rows.map{|r|r.last}.should == [
|
72
|
+
"dentist",
|
73
|
+
"student",
|
74
|
+
"student",
|
75
|
+
"student",
|
76
|
+
"student",
|
77
|
+
"teacher",
|
78
|
+
"teacher"
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should order columns ascending' do
|
83
|
+
g = PersonGrid.new :order => :profession, :desc => false
|
84
|
+
g.rows.size.should == 7
|
85
|
+
g.rows.map{|r|r.last}.should == [
|
86
|
+
"dentist",
|
87
|
+
"student",
|
88
|
+
"student",
|
89
|
+
"student",
|
90
|
+
"student",
|
91
|
+
"teacher",
|
92
|
+
"teacher"
|
93
|
+
]
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should order columns descending' do
|
97
|
+
g = PersonGrid.new :order => :profession, :desc => true
|
98
|
+
g.rows.size.should == 7
|
99
|
+
g.rows.map{|r|r.last}.should == [
|
100
|
+
"teacher",
|
101
|
+
"teacher",
|
102
|
+
"student",
|
103
|
+
"student",
|
104
|
+
"student",
|
105
|
+
"student",
|
106
|
+
"dentist"
|
107
|
+
]
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should order columns descending with given descend' do
|
111
|
+
g = PersonGrid.new :order => :profession, :desc => 'profession DESC'
|
112
|
+
g.rows.size.should == 7
|
113
|
+
g.rows.map{|r|r.last}.should == [
|
114
|
+
"teacher",
|
115
|
+
"teacher",
|
116
|
+
"student",
|
117
|
+
"student",
|
118
|
+
"student",
|
119
|
+
"student",
|
120
|
+
"dentist"
|
121
|
+
]
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should order complex columns' do
|
125
|
+
g = PersonGrid.new :order => :full_name
|
126
|
+
g.rows.size.should == 7
|
127
|
+
g.rows.should == [
|
128
|
+
["Dana", "Dana Twen", "teacher"],
|
129
|
+
["Dick", "Dick Teeny", "student"],
|
130
|
+
["Joe", "Joe Teen", "student"],
|
131
|
+
["John", "John Twen", "teacher"],
|
132
|
+
["Lisa", "Lisa Adult", "dentist"],
|
133
|
+
["Max", "Max Kid", "student"],
|
134
|
+
["Tina", "Tina Child", "student"]
|
135
|
+
]
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should order complex columns descending' do
|
139
|
+
g = PersonGrid.new :order => :full_name, :desc => true
|
140
|
+
g.rows.size.should == 7
|
141
|
+
g.rows.should == [
|
142
|
+
["Tina", "Tina Child", "student"],
|
143
|
+
["Max", "Max Kid", "student"],
|
144
|
+
["Lisa", "Lisa Adult", "dentist"],
|
145
|
+
["John", "John Twen", "teacher"],
|
146
|
+
["Joe", "Joe Teen", "student"],
|
147
|
+
["Dick", "Dick Teeny", "student"],
|
148
|
+
["Dana", "Dana Twen", "teacher"]
|
149
|
+
]
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should raise error for unknown order column' do
|
153
|
+
expect {
|
154
|
+
PersonGrid.new :order => :bla
|
155
|
+
}.to raise_error(
|
156
|
+
ArgumentError, /order/
|
157
|
+
)
|
158
|
+
end
|
159
|
+
end
|