easy-table 0.2.0
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/.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
|