easy-table 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/.rspec +1 -0
- data/LICENSE +20 -0
- data/README.markdown +167 -0
- data/Rakefile +24 -0
- data/VERSION +1 -0
- data/easy-table.gemspec +95 -0
- data/lib/easy-table.rb +2 -0
- data/lib/easy-table/cell.rb +38 -0
- data/lib/easy-table/namespaces.rb +8 -0
- data/lib/easy-table/rails_config.rb +7 -0
- data/lib/easy-table/row.rb +41 -0
- data/lib/easy-table/row/data.rb +36 -0
- data/lib/easy-table/table.rb +30 -0
- data/lib/easy-table/table/base.rb +29 -0
- data/lib/easy-table/table/data_table.rb +56 -0
- data/lib/easy-table/tag.rb +21 -0
- data/lib/easy-table/util.rb +27 -0
- data/lib/easy-table/view_extension.rb +19 -0
- data/spec/easy-table/cell_spec.rb +75 -0
- data/spec/easy-table/row/data_row_spec.rb +100 -0
- data/spec/easy-table/row/row_spec.rb +68 -0
- data/spec/easy-table/table/base_spec.rb +117 -0
- data/spec/easy-table/table/data_table_spec.rb +36 -0
- data/spec/easy-table/table/table_spec.rb +51 -0
- data/spec/easy-table/tag_spec.rb +38 -0
- data/spec/easy-table/util_spec.rb +67 -0
- data/spec/spec_helper.rb +8 -0
- metadata +193 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
module EasyTable::ViewExt::Row
|
2
|
+
module Data
|
3
|
+
def data_rows collection, attributes, options = {}
|
4
|
+
content = []
|
5
|
+
reset_cycle('rows')
|
6
|
+
collection.each do |obj|
|
7
|
+
row_content = data_row(obj, attributes, options)
|
8
|
+
content << indent(2) + row_content
|
9
|
+
end
|
10
|
+
content.join.html_safe
|
11
|
+
end
|
12
|
+
|
13
|
+
def data_row object, attributes, options={}
|
14
|
+
row_content = attribute_cells object, attributes, options.clone
|
15
|
+
|
16
|
+
cls_opt = class_option(:row_classes, options, :name => 'rows')
|
17
|
+
options[:row] ||= {}
|
18
|
+
options[:row].merge!(cls_opt)
|
19
|
+
|
20
|
+
indent_tag(2, :tr, row_content, options[:row]).html_safe
|
21
|
+
end
|
22
|
+
|
23
|
+
def attribute_cells object, attributes, options = {}
|
24
|
+
options.delete(:row_classes)
|
25
|
+
content = []
|
26
|
+
reset_cycle('cells')
|
27
|
+
attributes.each do |attrib|
|
28
|
+
cls_opt = class_option(:cell_classes, options, :name => 'cells')
|
29
|
+
|
30
|
+
content << cell(object, attrib, options.merge(cls_opt))
|
31
|
+
content << ''.indent(2) if attrib == attributes.last
|
32
|
+
end
|
33
|
+
content.join.html_safe
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'require_all'
|
2
|
+
require_all File.dirname(__FILE__) + '/table'
|
3
|
+
require 'easy-table/row'
|
4
|
+
|
5
|
+
module EasyTable::ViewExt
|
6
|
+
module Table
|
7
|
+
def table(collection, headers, options = {}, &block)
|
8
|
+
obj_type = get_obj_type collection
|
9
|
+
set_options! options
|
10
|
+
|
11
|
+
return options[:placeholder] unless collection.any?
|
12
|
+
|
13
|
+
options.delete :placeholder
|
14
|
+
caption = options.delete :caption
|
15
|
+
footer = options.delete :footer
|
16
|
+
|
17
|
+
|
18
|
+
render_table options do
|
19
|
+
[
|
20
|
+
render_caption(caption),
|
21
|
+
render_header(headers),
|
22
|
+
render_footer(footer, headers),
|
23
|
+
render_tbody(collection, &block)
|
24
|
+
].compact.join.html_safe
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
includes :base, :data
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'easy-table/row'
|
2
|
+
|
3
|
+
module EasyTable::ViewExt::Table
|
4
|
+
module Base
|
5
|
+
def render_table options = {}, &block
|
6
|
+
content_tag :table, options do
|
7
|
+
yield.indent(0)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def render_tbody collection, options={}, &block
|
12
|
+
indent_tag 1, :tbody do
|
13
|
+
table_body(collection, options, &block).indent(1)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def table_body collection, options = {}, &block
|
18
|
+
content = []
|
19
|
+
collection.each do |obj|
|
20
|
+
content << with_output_buffer { yield obj, options }
|
21
|
+
end
|
22
|
+
content.join.html_safe
|
23
|
+
end
|
24
|
+
|
25
|
+
def render_caption caption
|
26
|
+
indent_tag(1, :caption, caption) if !caption.blank?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module EasyTable::ViewExt::Table
|
2
|
+
module Data
|
3
|
+
def data_table(collection, headers, options = {})
|
4
|
+
obj_type = get_obj_type collection
|
5
|
+
set_options! options
|
6
|
+
|
7
|
+
return options[:placeholder] unless collection.any?
|
8
|
+
|
9
|
+
# try to extract attributes from headers!
|
10
|
+
attributes = options[:attributes] || extract_attributes(collection.first, headers)
|
11
|
+
|
12
|
+
arg_err = "You must specify an :attributes hash option to indicate which attributes of #{obj_type.camelize} should be rendered in the table!"
|
13
|
+
raise ArgumentError, arg_err if !attributes.any?
|
14
|
+
|
15
|
+
rows_options = options.delete(:rows) || {}
|
16
|
+
|
17
|
+
options.delete :placeholder
|
18
|
+
caption = options.delete :caption
|
19
|
+
footer = options.delete :footer
|
20
|
+
|
21
|
+
|
22
|
+
render_table options do
|
23
|
+
[
|
24
|
+
render_caption(caption),
|
25
|
+
render_header(headers),
|
26
|
+
render_footer(footer, headers),
|
27
|
+
indent_tag(1, :tbody) do
|
28
|
+
data_rows(collection, attributes, rows_options).indent 1
|
29
|
+
end
|
30
|
+
].compact.join
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def extract_attributes obj, headers
|
35
|
+
headers.map do |header|
|
36
|
+
att = header.to_s.underscore
|
37
|
+
attrib = obj.send att
|
38
|
+
att ? att : nil
|
39
|
+
end.compact
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_options! options={}, obj_type=nil
|
43
|
+
options.reverse_merge!({
|
44
|
+
:placeholder => 'Nothing to display',
|
45
|
+
:caption => nil,
|
46
|
+
:summary => nil,
|
47
|
+
:footer => '',
|
48
|
+
:class => obj_type
|
49
|
+
})
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_obj_type collection
|
53
|
+
collection.first.class.to_s
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module EasyTable::ViewExt
|
2
|
+
module Tag
|
3
|
+
def indent_tag lv, *args, &block
|
4
|
+
(indent(lv) + content_tag(*args, &block)).html_safe
|
5
|
+
end
|
6
|
+
|
7
|
+
def do_tag *args, &block
|
8
|
+
indent_tag 0, *args, &block
|
9
|
+
end
|
10
|
+
|
11
|
+
def indent(lv)
|
12
|
+
"\n" + (" " * lv)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class String
|
18
|
+
def indent lv
|
19
|
+
self << "\n" + (" " * lv)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'sugar-high/blank'
|
2
|
+
require 'sugar-high/array'
|
3
|
+
require 'sugar-high/arguments'
|
4
|
+
|
5
|
+
module EasyTable::ViewExt
|
6
|
+
module Util
|
7
|
+
def class_option id, options, cycle_options={}
|
8
|
+
return {} if !options[id]
|
9
|
+
{:class => get_class(options[id], :name => cycle_options[:name] || nil) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_class *classes
|
13
|
+
options = last_option classes
|
14
|
+
return cycle_class(options[:name]) if classes.blank?
|
15
|
+
|
16
|
+
classes = [classes].flatten
|
17
|
+
name = options[:name]
|
18
|
+
|
19
|
+
return cycle(*classes, :name => name) if name
|
20
|
+
cycle(*classes)
|
21
|
+
end
|
22
|
+
|
23
|
+
def cycle_class name=nil
|
24
|
+
name ? cycle('odd', 'even', :name => name) : cycle('odd', 'even')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
require 'require_all'
|
3
|
+
require 'sugar-high/includes'
|
4
|
+
require 'sugar-high/blank'
|
5
|
+
require 'sugar-high/blank'
|
6
|
+
require 'sugar-high/array'
|
7
|
+
|
8
|
+
require 'easy-table/namespaces'
|
9
|
+
|
10
|
+
require 'easy-table/table'
|
11
|
+
require 'easy-table/row'
|
12
|
+
require 'easy-table/cell'
|
13
|
+
require 'easy-table/tag'
|
14
|
+
|
15
|
+
module EasyTable
|
16
|
+
module ViewExt
|
17
|
+
includes :table, :row, :cell, :tag, :util
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'sugar-high/includes'
|
4
|
+
require 'easy-table/namespaces'
|
5
|
+
require 'easy-table/cell'
|
6
|
+
|
7
|
+
describe EasyTable::ViewExt::Cell do
|
8
|
+
extend_view_with EasyTable::ViewExt, :cell, :tag
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
@post = stub(:title => 'my post', :id => 1, :author => 'kristian' )
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#cell' do
|
15
|
+
it 'should display a cell with the post title' do
|
16
|
+
with_engine(:erb) do |e|
|
17
|
+
res = e.run_template_locals :post => @post do %{
|
18
|
+
<%= cell post, :title %>
|
19
|
+
}
|
20
|
+
end
|
21
|
+
res.should match(/<td>my post<\/td>/)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should display a cell with a class' do
|
26
|
+
with_engine(:erb) do |e|
|
27
|
+
res = e.run_template_locals :post => @post do %{
|
28
|
+
<%= cell post, :title, :class => 'posting' %>
|
29
|
+
}
|
30
|
+
end
|
31
|
+
res.should match(/<td class="posting">my post<\/td>/)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#cells' do
|
37
|
+
it 'should display cells for post' do
|
38
|
+
with_engine do |e|
|
39
|
+
res = e.run_template_locals :post => @post do %{
|
40
|
+
<%= cells post, %w{id title} %>
|
41
|
+
}
|
42
|
+
end
|
43
|
+
res.should match /<td>1<\/td>/
|
44
|
+
res.should match /<td>my post<\/td>/
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should display cells for post with classes' do
|
49
|
+
with_engine do |e|
|
50
|
+
res = e.run_template_locals :post => @post do %{
|
51
|
+
<%= cells post, %w{id title}, :classes => %w{red blue} %>
|
52
|
+
}
|
53
|
+
end
|
54
|
+
res.should match /<td class="red">1<\/td>/
|
55
|
+
res.should match /<td class="blue">my post<\/td>/
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#headers' do
|
61
|
+
it 'should display header cells' do
|
62
|
+
with_engine do |e|
|
63
|
+
res = e.run_template do %{
|
64
|
+
<%= header_row %w{Id Title} %>
|
65
|
+
}
|
66
|
+
end
|
67
|
+
res.should match /<th>Id<\/th>/
|
68
|
+
res.should match /<th>Title<\/th>/
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'sugar-high/includes'
|
4
|
+
require 'easy-table/namespaces'
|
5
|
+
require 'easy-table/cell'
|
6
|
+
require 'easy-table/row'
|
7
|
+
|
8
|
+
describe EasyTable::ViewExt::Row do
|
9
|
+
extend_view_with EasyTable::ViewExt, :row, :cell, :tag
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
@post = stub(:title => 'my post', :id => 1, :author => 'kristian' )
|
13
|
+
@post2 = stub(:title => 'my other post', :id => 2, :author => 'mike' )
|
14
|
+
|
15
|
+
@posts = [@post, @post2]
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#attribute_cells' do
|
19
|
+
it 'should display cells with data' do
|
20
|
+
with_engine(:erb) do |e|
|
21
|
+
res = e.run_template_locals :post => @post do %{
|
22
|
+
<%= attribute_cells post, %w{id title} %>
|
23
|
+
}
|
24
|
+
end
|
25
|
+
res.should_not match /<tr>/
|
26
|
+
res.should match /<td>1<\/td>/
|
27
|
+
res.should match /<td>my post<\/td>/
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#data_row' do
|
33
|
+
it 'should display a row with data' do
|
34
|
+
with_engine(:erb) do |e|
|
35
|
+
res = e.run_template_locals :post => @post do %{
|
36
|
+
<%= data_row post, %w{id title} %>
|
37
|
+
}
|
38
|
+
end
|
39
|
+
res.should match /<tr>/
|
40
|
+
res.should match /<td>1<\/td>/
|
41
|
+
res.should match /<td>my post<\/td>/
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should display a row with data and row class' do
|
46
|
+
with_engine(:erb) do |e|
|
47
|
+
res = e.run_template_locals :post => @post do %{
|
48
|
+
<%= data_row post, %w{id title}, :row => {:class => 'my_data_row'} %>
|
49
|
+
}
|
50
|
+
end
|
51
|
+
res.should match /<tr class="my_data_row">/
|
52
|
+
res.should match /<td>1<\/td>/
|
53
|
+
res.should match /<td>my post<\/td>/
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should display a row with data' do
|
58
|
+
with_engine(:erb) do |e|
|
59
|
+
res = e.run_template_locals :post => @post do %{
|
60
|
+
<%= data_row post, %w{id title}, :row => {:class => 'my_data_row'}, :cell_classes => %w{number label} %>
|
61
|
+
}
|
62
|
+
end
|
63
|
+
res.should match /<tr class="my_data_row">/
|
64
|
+
res.should match /<td class="number">1<\/td>/
|
65
|
+
res.should match /<td class="label">my post<\/td>/
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#data_rows' do
|
71
|
+
it 'should display a row with cells' do
|
72
|
+
with_engine(:erb) do |e|
|
73
|
+
res = e.run_template_locals :posts => @posts do %{
|
74
|
+
<%= data_rows posts, %w{id title} %>
|
75
|
+
}
|
76
|
+
end
|
77
|
+
res.should match /<tr>/
|
78
|
+
res.should match /<td>1<\/td>/
|
79
|
+
res.should match /<td>my post<\/td>/
|
80
|
+
res.should match /<td>2<\/td>/
|
81
|
+
res.should match /<td>my other post<\/td>/
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should display a row with cells with cycling classes' do
|
86
|
+
with_engine(:erb) do |e|
|
87
|
+
res = e.run_template_locals :posts => @posts do %{
|
88
|
+
<%= data_rows posts, %w{id title}, :row_classes => %w{row1 row2}, :cell_classes => %w{number label} %>
|
89
|
+
}
|
90
|
+
end
|
91
|
+
res.should match /<tr class="row1">/
|
92
|
+
res.should match /<tr class="row2">/
|
93
|
+
res.should match /<td class="number">1<\/td>/
|
94
|
+
res.should match /<td class="label">my post<\/td>/
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'sugar-high/includes'
|
4
|
+
require 'easy-table/namespaces'
|
5
|
+
require 'easy-table/row'
|
6
|
+
|
7
|
+
describe EasyTable::ViewExt::Row do
|
8
|
+
extend_view_with EasyTable::ViewExt, :row, :cell, :tag
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
@post = stub(:title => 'my post', :id => 1, :author => 'kristian' )
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#row' do
|
15
|
+
it 'should display a cell with the post title' do
|
16
|
+
with_engine(:erb) do |e|
|
17
|
+
res = e.run_template_locals :post => @post do %{
|
18
|
+
<%= row post, :class => :mine do |post| %>
|
19
|
+
<%= cells post, %w{id title} %>
|
20
|
+
<% end %>
|
21
|
+
}
|
22
|
+
end
|
23
|
+
res.should match /<tr class="mine">/
|
24
|
+
res.should match /<td>1<\/td>/
|
25
|
+
res.should match /<td>my post<\/td>/
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#render_header' do
|
31
|
+
it 'should display a header with header cells' do
|
32
|
+
with_engine(:erb) do |e|
|
33
|
+
res = e.run_template_locals :post => @post do %{
|
34
|
+
<%= render_header %w{Id Title} %>
|
35
|
+
}
|
36
|
+
end
|
37
|
+
res.should match /<thead>/
|
38
|
+
res.should match /<tr>/
|
39
|
+
res.should match /<th>Id<\/th>/
|
40
|
+
res.should match /<th>Title<\/th>/
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#render_footer' do
|
46
|
+
it 'should display a footer spanning the length of the header' do
|
47
|
+
with_engine(:erb) do |e|
|
48
|
+
res = e.run_template_locals :post => @post do %{
|
49
|
+
<%= render_footer 'a nice table', %w{id title} %>
|
50
|
+
}
|
51
|
+
end
|
52
|
+
res.should match /<tfoot>/
|
53
|
+
res.should match /colspan="2"/
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should display a footer spanning 2 cells' do
|
58
|
+
with_engine(:erb) do |e|
|
59
|
+
res = e.run_template_locals :post => @post do %{
|
60
|
+
<%= render_footer 'a nice table', 2%>
|
61
|
+
}
|
62
|
+
end
|
63
|
+
res.should match /<tfoot>/
|
64
|
+
res.should match /colspan="2"/
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|