easy-table 0.2.0

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