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/spec/facets_spec.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def check_facet( facets, name, label, size )
|
4
|
+
f = facets.detect{|f|f.name == name}
|
5
|
+
f.should_not == nil
|
6
|
+
f.name.should == name
|
7
|
+
f.label.should == label
|
8
|
+
data = f.data(:include_zeros => true)
|
9
|
+
data.size.should == size
|
10
|
+
data.each do |v|
|
11
|
+
v.name.should == name
|
12
|
+
end
|
13
|
+
f
|
14
|
+
end
|
15
|
+
|
16
|
+
def check_facet_value( facet, value, count )
|
17
|
+
v = facet.data.detect{|v|v.value == value}
|
18
|
+
v.should_not == nil
|
19
|
+
v.value.should == value
|
20
|
+
v.count.should == count
|
21
|
+
v.params.should == { v.name => value }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Gitter do
|
25
|
+
|
26
|
+
context 'facets' do
|
27
|
+
it 'should manage facets' do
|
28
|
+
PersonGrid.facets.count.should == 5
|
29
|
+
PersonGrid.facets.size.should == 5
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should handle facets ' do
|
33
|
+
class Bla < Gitter::Grid
|
34
|
+
filter :foo, :facet => true
|
35
|
+
filter :bar
|
36
|
+
end
|
37
|
+
Bla.facets.count.should == 1
|
38
|
+
Bla.facets.should include(:foo)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should manage column facets' do
|
42
|
+
facets = PersonGrid.new.facets
|
43
|
+
f = check_facet facets, :sex, 'Sex', 2
|
44
|
+
check_facet_value f, 'f', 3
|
45
|
+
check_facet_value f, 'm', 4
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should manage boolean column facets' do
|
49
|
+
facets = PersonGrid.new.facets
|
50
|
+
f = check_facet facets, :teen_with_facet, 'Teen', 2
|
51
|
+
check_facet_value f, true, 2
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should manage select facets' do
|
55
|
+
facets = PersonGrid.new.facets
|
56
|
+
|
57
|
+
f = check_facet facets, :age, 'Age', 4
|
58
|
+
check_facet_value f, :child, 2
|
59
|
+
check_facet_value f, :teen, 2
|
60
|
+
check_facet_value f, :twen, 2
|
61
|
+
check_facet_value f, :other, 1
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should manage select facets with scope' do
|
65
|
+
g = PersonGrid.new(:profession => 'student')
|
66
|
+
facets = g.facets
|
67
|
+
|
68
|
+
f = check_facet facets, :age, 'Age', 4
|
69
|
+
check_facet_value f, :child, 2
|
70
|
+
check_facet_value f, :teen, 2
|
71
|
+
check_facet_value f, :twen, 0
|
72
|
+
check_facet_value f, :other, 0
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/grid_spec.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Persons
|
4
|
+
include Gitter
|
5
|
+
|
6
|
+
describe Grid do
|
7
|
+
|
8
|
+
it 'should have a name' do
|
9
|
+
PersonGrid.new.name.should == 'person_grid'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should handle a scope' do
|
13
|
+
class Foo < Grid
|
14
|
+
scope do
|
15
|
+
'bla'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Foo.new.scope.should == 'bla'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should handle scope with helpers' do
|
23
|
+
class Foo < Grid
|
24
|
+
scope do
|
25
|
+
h.foo
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
vc = Struct.new(:foo).new('bar')
|
30
|
+
|
31
|
+
g = Foo.new(:view_context => vc)
|
32
|
+
g.scope.should == 'bar'
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should have a default driver' do
|
37
|
+
class Foo < Grid
|
38
|
+
scope do
|
39
|
+
'bla'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Foo.driver_class.should == ActiveRecordDriver
|
44
|
+
Foo.new.scope.should == 'bla'
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should handle given driver' do
|
48
|
+
class MyDriver < AbstractDriver
|
49
|
+
end
|
50
|
+
|
51
|
+
class Foo < Grid
|
52
|
+
driver_class MyDriver
|
53
|
+
scope do
|
54
|
+
'bla'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Foo.driver_class.should == MyDriver
|
59
|
+
Foo.new.scope.should == 'bla'
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should complain for unset scope' do
|
63
|
+
class Bar < Grid
|
64
|
+
end
|
65
|
+
|
66
|
+
expect {
|
67
|
+
Bar.scope
|
68
|
+
}.to raise_error(
|
69
|
+
ConfigurationError
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should handle filters' do
|
74
|
+
class Foo2 < Grid
|
75
|
+
filter :foo
|
76
|
+
filter :bar
|
77
|
+
end
|
78
|
+
|
79
|
+
Foo2.filter_specs.count.should == 2
|
80
|
+
Foo2.filter_specs[:foo].should_not == nil
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should handle columns ' do
|
84
|
+
class Foo4 < Grid
|
85
|
+
column :foo
|
86
|
+
column :bar
|
87
|
+
end
|
88
|
+
Foo4.column_specs.count.should == 2
|
89
|
+
Foo4.column_specs[:foo].should_not == nil
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
data/spec/helper_spec.rb
ADDED
data/spec/i18n_spec.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Persons
|
4
|
+
|
5
|
+
def __find__( clazz, what, name )
|
6
|
+
g = clazz.new name => 'bla'
|
7
|
+
f = g.send(what).detect{|w|w.name == name}
|
8
|
+
f.name.should == name
|
9
|
+
f
|
10
|
+
end
|
11
|
+
|
12
|
+
def check_local( en, de )
|
13
|
+
I18n.locale = :en
|
14
|
+
yield.should == en
|
15
|
+
I18n.locale = :de
|
16
|
+
yield.should == de
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'I18n' do
|
20
|
+
it 'should translate filter labels' do
|
21
|
+
check_local('en_name', 'de_name'){ __find__(PersonGrid, :filters, :localname).label }
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should translate facet labels' do
|
25
|
+
check_local('en_label', 'de_label'){ __find__(PersonGrid, :facets, :localname).label }
|
26
|
+
end
|
27
|
+
|
28
|
+
class HeaderGrid < Gitter::Grid
|
29
|
+
grid do
|
30
|
+
scope do Person.scoped end
|
31
|
+
column :localname, :column => :name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should translate column headers' do
|
36
|
+
check_local('en_header', 'de_header'){ __find__(HeaderGrid, :columns, :localname).header }
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/spec/inputs_spec.rb
ADDED
File without changes
|
data/spec/locales/de.yml
ADDED
data/spec/locales/en.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Persons
|
4
|
+
|
5
|
+
describe Gitter do
|
6
|
+
|
7
|
+
context 'range filter' do
|
8
|
+
it 'should complain for given block' do
|
9
|
+
expect {
|
10
|
+
class RangeFilterErr < Gitter::Grid
|
11
|
+
filter :name, :range => true do
|
12
|
+
# something
|
13
|
+
end
|
14
|
+
end
|
15
|
+
}.to raise_error(
|
16
|
+
Gitter::ConfigurationError, /no block allowed/
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'filter with range' do
|
22
|
+
check_include Joe, Dick, :birthday => (Date.new(1995,1,1)...Date.new(1997,1,1))
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'filter with from ...to range' do
|
26
|
+
check_include Joe, Dick, :from_birthday => Date.new(1995,1,1), :to_birthday => Date.new(1997,1,1)
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'filter with range and given :from, :to' do
|
30
|
+
check_include Joe, Dick, :between => Date.new(1995,1,1), :and => Date.new(1997,1,1)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Persons
|
4
|
+
|
5
|
+
describe Gitter do
|
6
|
+
|
7
|
+
context 'filter with select' do
|
8
|
+
check_include Joe, Dick, :age => :teen
|
9
|
+
check_include Dana, John, :age => :twen
|
10
|
+
check_include Lisa, :age => :other
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'filter with select for scopes' do
|
14
|
+
check_include Tina, Dana, Lisa, :sex_scope => :female_scope
|
15
|
+
check_include Max, Joe, Dick, John, :sex_scope => :male_scope
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'filter with select for scopes and filters' do
|
19
|
+
check_include Tina, Dana, Lisa, :mixed_select => :female_scope
|
20
|
+
check_include Joe, Dick, :mixed_select => :teen
|
21
|
+
end
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#require 'rubygems'
|
2
|
+
#require 'bundler'
|
3
|
+
#Bundler.setup :default, :development
|
4
|
+
|
5
|
+
require 'rspec'
|
6
|
+
require 'i18n'
|
7
|
+
require 'gitter'
|
8
|
+
|
9
|
+
I18n.load_path = Dir[File.dirname(__FILE__) + '/locales/*.yml']
|
10
|
+
I18n.default_locale = :en
|
11
|
+
|
12
|
+
require 'support/database'
|
13
|
+
Dir[File.dirname(__FILE__) + '/support/*.rb'].each{|f| require f}
|
14
|
+
|
15
|
+
def check_include(*args)
|
16
|
+
params = args.extract_options!
|
17
|
+
scope = PersonGrid.new(:params => params).scope
|
18
|
+
all = Set.new scope.all
|
19
|
+
expected = Set.new [args].flatten
|
20
|
+
#puts "SSSSSSSSSSS scope=#{scope.to_sql}"
|
21
|
+
#puts " all=#{all.inspect}"
|
22
|
+
#puts " expected=#{expected.inspect}"
|
23
|
+
specify { all.should == expected }
|
24
|
+
end
|
25
|
+
|
26
|
+
class Array
|
27
|
+
def detect_name( name)
|
28
|
+
detect{|d| d.name == name }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
|
3
|
+
|
4
|
+
ActiveRecord::Schema.define do
|
5
|
+
create_table :people do |t|
|
6
|
+
t.string :name, :surname, :sex, :profession
|
7
|
+
t.date :birthday
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Person < ActiveRecord::Base
|
12
|
+
scope :male_scope, where(:sex => 'm')
|
13
|
+
scope :female_scope, where(:sex => 'f')
|
14
|
+
end
|
15
|
+
|
16
|
+
module Persons
|
17
|
+
Max = Person.create :name => 'Max', :surname => 'Kid', :birthday => Date.new(2003,1,1), :sex => 'm', :profession => 'student'
|
18
|
+
Tina = Person.create :name => 'Tina', :surname => 'Child', :birthday => Date.new(2002,1,1), :sex => 'f', :profession => 'student'
|
19
|
+
Joe = Person.create :name => 'Joe', :surname => 'Teen', :birthday => Date.new(1995,1,1), :sex => 'm', :profession => 'student'
|
20
|
+
Dick = Person.create :name => 'Dick', :surname => 'Teeny', :birthday => Date.new(1996,1,1), :sex => 'm', :profession => 'student'
|
21
|
+
Dana = Person.create :name => 'Dana', :surname => 'Twen', :birthday => Date.new(1985,1,1), :sex => 'f', :profession => 'teacher'
|
22
|
+
John = Person.create :name => 'John', :surname => 'Twen', :birthday => Date.new(1985,2,1), :sex => 'm', :profession => 'teacher'
|
23
|
+
Lisa = Person.create :name => 'Lisa', :surname => 'Adult', :birthday => Date.new(1980,2,1), :sex => 'f', :profession => 'dentist'
|
24
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class PersonGrid < Gitter::Grid
|
2
|
+
|
3
|
+
grid do
|
4
|
+
scope do
|
5
|
+
Person.scoped
|
6
|
+
end
|
7
|
+
|
8
|
+
today = Time.utc(2011,01,01)
|
9
|
+
|
10
|
+
filter :name, :facet => true
|
11
|
+
filter :name2, :column => :name
|
12
|
+
filter :name3, :column => :name, :label => 'Three'
|
13
|
+
filter :localname, :column => :name, :facet => true
|
14
|
+
|
15
|
+
filter :surname, :label => 'Surname'
|
16
|
+
filter :profession
|
17
|
+
|
18
|
+
filter :birthday, :range => true
|
19
|
+
filter :birthday, :from => :between, :to => :and, :range => true
|
20
|
+
|
21
|
+
filter :sex, :facet => true
|
22
|
+
|
23
|
+
filter :teen_with_facet, :label => 'Teen', :facet => true do |scope|
|
24
|
+
scope.where :birthday => (today - 19.years...today - 10.years)
|
25
|
+
end
|
26
|
+
|
27
|
+
filter :teen do |scope|
|
28
|
+
scope.where :birthday => (today - 19.years...today - 10.years)
|
29
|
+
end
|
30
|
+
|
31
|
+
filter :twen do |scope|
|
32
|
+
scope.where :birthday => (today - 29.years...today - 20.years)
|
33
|
+
end
|
34
|
+
|
35
|
+
filter :child do |scope|
|
36
|
+
scope.where :birthday => (today - 10.years...today)
|
37
|
+
end
|
38
|
+
|
39
|
+
filter :other do |scope|
|
40
|
+
scope.where [ 'birthday <= ?', today - 29.years ]
|
41
|
+
end
|
42
|
+
|
43
|
+
filter :adult do |scope|
|
44
|
+
scope.where [ 'birthday <= ?', today - 18.years ]
|
45
|
+
end
|
46
|
+
|
47
|
+
filter :age, :select => [:child, :teen, :twen, :other], :facet => true
|
48
|
+
|
49
|
+
filter :male_scope, :scope => true
|
50
|
+
filter :female_scope, :scope => :female_scope
|
51
|
+
|
52
|
+
filter :sex_scope, :select => [:male_scope, :female_scope]
|
53
|
+
filter :mixed_select, :select => [:female_scope, :teen]
|
54
|
+
|
55
|
+
filter :any_name, :columns => [:name, :surname]
|
56
|
+
filter :name_ignore, :columns => :name, :ignore_case => true
|
57
|
+
filter :name_inexact, :columns => :name, :exact => false
|
58
|
+
filter :name_inexact_ignore, :columns => :name, :exact => false, :ignore_case => true
|
59
|
+
filter :name_inexact_no_ignore, :columns => :name, :exact => false, :ignore_case => false
|
60
|
+
|
61
|
+
search :search_name, :column => :name
|
62
|
+
|
63
|
+
column :name, :order => true
|
64
|
+
|
65
|
+
column :full_name, :order => 'name, surname', :order_desc => 'name DESC, surname DESC' do
|
66
|
+
"#{name} #{surname}"
|
67
|
+
end
|
68
|
+
|
69
|
+
column :profession, :header => 'Job Title', :order => true
|
70
|
+
end
|
71
|
+
end
|