easy_table 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +11 -0
- data/LICENSE +22 -0
- data/README.md +152 -0
- data/Rakefile +14 -0
- data/easy_table.gemspec +21 -0
- data/lib/easy_table.rb +15 -0
- data/lib/easy_table/action_view_extensions/table_helper.rb +14 -0
- data/lib/easy_table/components/base.rb +10 -0
- data/lib/easy_table/components/column.rb +57 -0
- data/lib/easy_table/components/columns.rb +22 -0
- data/lib/easy_table/components/span.rb +44 -0
- data/lib/easy_table/components/spans.rb +27 -0
- data/lib/easy_table/table_builder.rb +70 -0
- data/lib/easy_table/version.rb +3 -0
- data/test/action_view_extensions/table_helper_test.rb +135 -0
- data/test/components/spans_test.rb +39 -0
- data/test/table_builder_test.rb +5 -0
- data/test/test_helper.rb +31 -0
- metadata +101 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Jakub Głuszecki
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
# EasyTable
|
2
|
+
|
3
|
+
EasyTable provides a helper for building HTML tables in Rails applications.
|
4
|
+
|
5
|
+
It is inspired by simple_form gem: https://github.com/plataformatec/simple_form
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'easy_table', :git => 'https://github.com/cthulhu666/easy_table.git'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
All examples assume that You are using Haml. Please, use Haml !
|
20
|
+
|
21
|
+
### Simplest example
|
22
|
+
|
23
|
+
```haml
|
24
|
+
= table_for(@people) do |t|
|
25
|
+
- t.column :name
|
26
|
+
- t.column :surname
|
27
|
+
```
|
28
|
+
|
29
|
+
This produces:
|
30
|
+
|
31
|
+
```haml
|
32
|
+
%table
|
33
|
+
%thead
|
34
|
+
%tr
|
35
|
+
%th name
|
36
|
+
%th surname
|
37
|
+
%tbody
|
38
|
+
%tr#person-1
|
39
|
+
%td John
|
40
|
+
%td Doe
|
41
|
+
```
|
42
|
+
|
43
|
+
Assuming `@people` is a collection consisting of one record, person with id = 1, John Doe
|
44
|
+
|
45
|
+
### Simple example
|
46
|
+
|
47
|
+
```haml
|
48
|
+
= table_for(@people, class: 'people') do |t|
|
49
|
+
- t.column :name, class: 'name' do |person|
|
50
|
+
- person.name.downcase
|
51
|
+
- t.column :surname, class: lambda { |person| ['surname', person.surname.length > 5 && 'long'].compact } do |person|
|
52
|
+
- person.surname.upcase
|
53
|
+
```
|
54
|
+
|
55
|
+
This produces:
|
56
|
+
|
57
|
+
```haml
|
58
|
+
%table.people
|
59
|
+
%thead
|
60
|
+
%tr
|
61
|
+
%th name
|
62
|
+
%th surname
|
63
|
+
%tbody
|
64
|
+
%tr#person-1
|
65
|
+
%td.name john
|
66
|
+
%td.surname DOE
|
67
|
+
%tr#person-2
|
68
|
+
%td.name alice
|
69
|
+
%td.surname.long COOPER
|
70
|
+
```
|
71
|
+
|
72
|
+
Assuming `@people` is a collection consisting of two records:
|
73
|
+
* person with id = 1, John Doe
|
74
|
+
* person with id = 2, Alice Cooper
|
75
|
+
|
76
|
+
### Example with more complex table structure
|
77
|
+
|
78
|
+
```haml
|
79
|
+
= table_for(@people) do |t|
|
80
|
+
- t.span 'personal data' do |s|
|
81
|
+
- s.column :name
|
82
|
+
- s.colunm :surname
|
83
|
+
- t.span 'contact data' do |s|
|
84
|
+
- s.column :email
|
85
|
+
- s.column :phone
|
86
|
+
```
|
87
|
+
|
88
|
+
This produces:
|
89
|
+
|
90
|
+
```haml
|
91
|
+
%table
|
92
|
+
%thead
|
93
|
+
%tr
|
94
|
+
%th{colspan: 2, scope: 'col'} personal data
|
95
|
+
%th{colspan: 2, scope: 'col'} contact data
|
96
|
+
%tr
|
97
|
+
%th name
|
98
|
+
%th surname
|
99
|
+
%th email
|
100
|
+
%th phone
|
101
|
+
%tbody
|
102
|
+
%tr#person-1
|
103
|
+
%td John
|
104
|
+
%td Doe
|
105
|
+
%td john.doe@gmail.com
|
106
|
+
%td 123456789
|
107
|
+
```
|
108
|
+
|
109
|
+
### I18n and column headers
|
110
|
+
|
111
|
+
```yaml
|
112
|
+
en:
|
113
|
+
easy_table:
|
114
|
+
person: # this is matched based on controller_name.singularize
|
115
|
+
name: 'Name'
|
116
|
+
surname: 'Surname'
|
117
|
+
```
|
118
|
+
|
119
|
+
With following form definition
|
120
|
+
|
121
|
+
```haml
|
122
|
+
= table_for(@people) do |t|
|
123
|
+
- t.column :name
|
124
|
+
- t.column :surname
|
125
|
+
```
|
126
|
+
|
127
|
+
It will use 'Name' and 'Surname' as column header labels:
|
128
|
+
|
129
|
+
```haml
|
130
|
+
%table
|
131
|
+
%thead
|
132
|
+
%tr
|
133
|
+
%th Name
|
134
|
+
%th Surname
|
135
|
+
```
|
136
|
+
|
137
|
+
You can also explicitly set column header passing it as a second argument to ```column``` and ```span``` methods:
|
138
|
+
|
139
|
+
```haml
|
140
|
+
= table_for(@people) do |t|
|
141
|
+
- t.column :name, 'Name'
|
142
|
+
- t.column :surname, 'Surname'
|
143
|
+
```
|
144
|
+
|
145
|
+
|
146
|
+
## Contributing
|
147
|
+
|
148
|
+
1. Fork it
|
149
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
150
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
151
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
152
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the simple_form plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.libs << 'test'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
data/easy_table.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/easy_table/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Jakub Głuszecki"]
|
6
|
+
gem.email = ["jakub.gluszecki@gmail.com"]
|
7
|
+
gem.description = "HTML tables made easy (in Rails 3)"
|
8
|
+
gem.summary = "HTML tables made easy (in Rails 3)"
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "easy_table"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = EasyTable::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency('activemodel', '~> 3.0')
|
19
|
+
gem.add_dependency('actionpack', '~> 3.0')
|
20
|
+
gem.add_dependency 'rubytree'
|
21
|
+
end
|
data/lib/easy_table.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "easy_table/version"
|
2
|
+
|
3
|
+
require 'action_view'
|
4
|
+
require 'easy_table/action_view_extensions/table_helper'
|
5
|
+
require 'easy_table/components/base'
|
6
|
+
require 'easy_table/components/columns'
|
7
|
+
require 'easy_table/components/column'
|
8
|
+
require 'easy_table/components/spans'
|
9
|
+
require 'easy_table/components/span'
|
10
|
+
require 'easy_table/table_builder'
|
11
|
+
require 'tree'
|
12
|
+
|
13
|
+
module EasyTable
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module EasyTable
|
2
|
+
module ActionViewExtensions
|
3
|
+
module TableHelper
|
4
|
+
def table_for(collection, options = {}, &block)
|
5
|
+
t = EasyTable::TableBuilder.new(collection, self, options)
|
6
|
+
block.yield(t) if block_given?
|
7
|
+
t.build
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
ActionView::Base.send :include, EasyTable::ActionViewExtensions::TableHelper
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module EasyTable
|
2
|
+
module Components
|
3
|
+
class Column
|
4
|
+
include Base
|
5
|
+
|
6
|
+
delegate :tag, :capture, :content_tag, :to => :@template
|
7
|
+
|
8
|
+
def initialize(node, title, label, opts, template, block)
|
9
|
+
@node, @title, @label, @template, @block, @opts = node, title, label, template, block, opts
|
10
|
+
header_opts = @opts.select { |k, v| k =~ /^header_.*/ }
|
11
|
+
header_opts.each { |k, v| @opts.delete(k) }
|
12
|
+
@header_opts = header_opts.inject({}) do |h, e|
|
13
|
+
k, v = *e
|
14
|
+
h[k[7..-1]] = v
|
15
|
+
h
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def head
|
20
|
+
concat content_tag(:th, label, @header_opts)
|
21
|
+
end
|
22
|
+
|
23
|
+
def td(record)
|
24
|
+
if @block.present?
|
25
|
+
html = capture { @block.call(record, self) }
|
26
|
+
else
|
27
|
+
html = record.send(@title).to_s
|
28
|
+
end
|
29
|
+
concat(content_tag(:td, html, html_opts(record)))
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def label
|
35
|
+
@label || translate(@title)
|
36
|
+
end
|
37
|
+
|
38
|
+
def concat(tag)
|
39
|
+
@template.safe_concat(tag) unless tag.nil?
|
40
|
+
""
|
41
|
+
end
|
42
|
+
|
43
|
+
def html_opts(record)
|
44
|
+
@opts.inject({}) do |h, e|
|
45
|
+
k, v = *e
|
46
|
+
h[k] = case v
|
47
|
+
when Proc
|
48
|
+
v.call(record)
|
49
|
+
else
|
50
|
+
v
|
51
|
+
end
|
52
|
+
h
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module EasyTable
|
2
|
+
module Components
|
3
|
+
module Columns
|
4
|
+
def column(title, label_or_opts = nil, opts = {}, &block)
|
5
|
+
if label_or_opts.is_a?(Hash) && label_or_opts.extractable_options?
|
6
|
+
label, opts = nil, label_or_opts
|
7
|
+
else
|
8
|
+
label, opts = label_or_opts, opts
|
9
|
+
end
|
10
|
+
child = node << Tree::TreeNode.new(title)
|
11
|
+
column = Column.new(child, title, label, opts, @template, block)
|
12
|
+
child.content = column
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def node
|
18
|
+
@node
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module EasyTable
|
2
|
+
module Components
|
3
|
+
class Span
|
4
|
+
include Base
|
5
|
+
include Columns
|
6
|
+
include Spans
|
7
|
+
|
8
|
+
def initialize(node, title, label, html_opts, template, block)
|
9
|
+
@node, @title, @label, @template, @block, @html_opts = node, title, label, template, block, html_opts
|
10
|
+
block.call(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
delegate :tag, :content_tag, :to => :@template
|
14
|
+
|
15
|
+
def head
|
16
|
+
opts = @html_opts.merge(colspan: colspan, scope: 'col')
|
17
|
+
concat content_tag(:th, label, opts)
|
18
|
+
end
|
19
|
+
|
20
|
+
def td(record)
|
21
|
+
columns.each do |col|
|
22
|
+
col.td(record)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def label
|
29
|
+
return nil if @title.nil?
|
30
|
+
@label || translate(@title)
|
31
|
+
end
|
32
|
+
|
33
|
+
def colspan
|
34
|
+
node.inject(0) { |count, n| count += 1 if n.is_leaf?; count }
|
35
|
+
end
|
36
|
+
|
37
|
+
def concat(tag)
|
38
|
+
@template.safe_concat(tag)
|
39
|
+
""
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module EasyTable
|
2
|
+
module Components
|
3
|
+
module Spans
|
4
|
+
def span(*args, &block)
|
5
|
+
opts = options_from_hash(args)
|
6
|
+
title, label = *args
|
7
|
+
child = node << Tree::TreeNode.new(title || generate_node_name)
|
8
|
+
span = Span.new(child, title, label, opts, @template, block)
|
9
|
+
child.content = span
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def node
|
15
|
+
@node
|
16
|
+
end
|
17
|
+
|
18
|
+
def options_from_hash(args)
|
19
|
+
args.last.is_a?(Hash) ? args.pop : {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def generate_node_name
|
23
|
+
"#{node.name}-span-#{node.size}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module EasyTable
|
2
|
+
class TableBuilder
|
3
|
+
|
4
|
+
include EasyTable::Components::Columns
|
5
|
+
include EasyTable::Components::Spans
|
6
|
+
|
7
|
+
delegate :tag, :content_tag, :to => :@template
|
8
|
+
|
9
|
+
def initialize(collection, template, options)
|
10
|
+
@collection = collection
|
11
|
+
@options = options
|
12
|
+
@template = template
|
13
|
+
@node = Tree::TreeNode.new('root')
|
14
|
+
end
|
15
|
+
|
16
|
+
def build
|
17
|
+
content_tag(:table, @options) do
|
18
|
+
concat(content_tag(:thead) do
|
19
|
+
thead
|
20
|
+
end)
|
21
|
+
concat(content_tag(:tbody) do
|
22
|
+
@collection.each do |record|
|
23
|
+
concat(content_tag(:tr, tr_opts(record)) do
|
24
|
+
node.each_leaf do |leaf|
|
25
|
+
leaf.content.td(record)
|
26
|
+
end
|
27
|
+
end)
|
28
|
+
end
|
29
|
+
end)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def thead
|
36
|
+
rows = node.inject([]) do |arr, n|
|
37
|
+
arr[n.level] ||= []
|
38
|
+
arr[n.level] << n
|
39
|
+
arr
|
40
|
+
end
|
41
|
+
rows.shift
|
42
|
+
rows.each do |row|
|
43
|
+
concat(
|
44
|
+
content_tag(:tr) do
|
45
|
+
row.map { |node| node.content }.each do |span_or_column|
|
46
|
+
span_or_column.head
|
47
|
+
end
|
48
|
+
end
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def tr_opts(record)
|
54
|
+
id = "#{record.class.model_name.parameterize}-#{record.to_param}" if record.class.respond_to?(:model_name)
|
55
|
+
id ||= "#{record.class.name.parameterize}-#{record.id}" if record.respond_to?(:id)
|
56
|
+
|
57
|
+
id.present? ?
|
58
|
+
{id: id} : {}
|
59
|
+
end
|
60
|
+
|
61
|
+
def concat(tag)
|
62
|
+
@template.safe_concat(tag)
|
63
|
+
""
|
64
|
+
end
|
65
|
+
|
66
|
+
def options_from_hash(args)
|
67
|
+
args.last.is_a?(Hash) ? args.pop : {}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
if __FILE__== $0
|
2
|
+
require '../test_helper'
|
3
|
+
else
|
4
|
+
require 'test_helper'
|
5
|
+
end
|
6
|
+
|
7
|
+
class TableHelperTest < ActionView::TestCase
|
8
|
+
|
9
|
+
context "a table" do
|
10
|
+
setup do
|
11
|
+
@collection = ['foo', 'bar', 'buzz']
|
12
|
+
concat(table_for(@collection, class: 'easy') do |t|
|
13
|
+
t.column :downcase
|
14
|
+
t.column(:upcase) { |t| t.upcase }
|
15
|
+
end)
|
16
|
+
end
|
17
|
+
|
18
|
+
should "have 'easy' class" do
|
19
|
+
assert_select 'table.easy'
|
20
|
+
end
|
21
|
+
|
22
|
+
should "have 3 rows" do
|
23
|
+
rows = css_select 'table tbody tr'
|
24
|
+
assert_equal 3, rows.size
|
25
|
+
end
|
26
|
+
|
27
|
+
should "have 2 columns" do
|
28
|
+
cols = css_select 'table tbody tr:first-child td'
|
29
|
+
assert_equal 2, cols.size
|
30
|
+
end
|
31
|
+
|
32
|
+
should "have proper headers" do
|
33
|
+
headers = css_select 'table thead tr th'
|
34
|
+
assert_equal '<th>downcase</th>', headers[0].to_s
|
35
|
+
assert_equal '<th>upcase</th>', headers[1].to_s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "a complex table" do
|
40
|
+
setup do
|
41
|
+
Person = Struct.new(:id, :name, :surname, :email, :phone) unless defined?(Person)
|
42
|
+
@collection = []
|
43
|
+
@collection << Person.new(1, "John", "Doe", "jdoe@gmail.com", "500600700")
|
44
|
+
@collection << Person.new(2, "Barack", "Obama", "bobama@polskieobozy.com", "501601701")
|
45
|
+
concat(table_for(@collection) do |t|
|
46
|
+
t.span(:names) do |s|
|
47
|
+
s.column :name, class: 'name', header_class: 'name_head'
|
48
|
+
s.column(:surname) { |person| content_tag(:span, person.surname.capitalize) }
|
49
|
+
end
|
50
|
+
t.span(:contact_data) do |s|
|
51
|
+
s.column :email, class: lambda { |person| ['foo', 'bar', person.email =~ /gmail/ && 'gmail'].compact }
|
52
|
+
s.column :phone
|
53
|
+
end
|
54
|
+
end)
|
55
|
+
end
|
56
|
+
|
57
|
+
should "have rows with proper id attributes" do
|
58
|
+
assert_select 'table tbody tr#tablehelpertest-person-1'
|
59
|
+
assert_select 'table tbody tr#tablehelpertest-person-2'
|
60
|
+
end
|
61
|
+
|
62
|
+
should "have 2 th-s in thead's first row'" do
|
63
|
+
row = css_select 'table thead tr:first-child th'
|
64
|
+
assert_equal 2, row.size
|
65
|
+
end
|
66
|
+
|
67
|
+
should "have 4 th-s in thead's second row'" do
|
68
|
+
row = css_select 'table thead tr:nth-child(2) th'
|
69
|
+
assert_equal 4, row.size
|
70
|
+
end
|
71
|
+
|
72
|
+
should "have proper body content" do
|
73
|
+
assert_select 'table tbody tr:first-child td:first-child', {count: 1, text: 'John'}
|
74
|
+
assert_select 'table tbody tr:first-child td:nth-child(2) span', {count: 1, text: 'Doe'}
|
75
|
+
end
|
76
|
+
|
77
|
+
should "have proper td class in name column" do
|
78
|
+
td = css_select('table tbody tr:first-child td:first-child').first
|
79
|
+
assert_equal 'name', td.attributes['class']
|
80
|
+
end
|
81
|
+
|
82
|
+
should "have proper th class in name column" do
|
83
|
+
td = css_select('table thead tr:nth-child(2) th:first-child').first
|
84
|
+
assert_equal 'name_head', td.attributes['class']
|
85
|
+
end
|
86
|
+
|
87
|
+
should "have proper td class in first row in email column" do
|
88
|
+
td = css_select('table tbody tr:nth-child(1) td:nth-child(3)').first
|
89
|
+
assert_equal 'foo bar gmail', td.attributes['class']
|
90
|
+
end
|
91
|
+
|
92
|
+
should "have proper td class in second row in email column" do
|
93
|
+
td = css_select('table tbody tr:nth-child(2) td:nth-child(3)').first
|
94
|
+
assert_equal 'foo bar', td.attributes['class']
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "table with nested spans" do
|
99
|
+
setup do
|
100
|
+
@collection = []
|
101
|
+
concat(
|
102
|
+
table_for(@collection) do |t|
|
103
|
+
t.span :span1 do |s1|
|
104
|
+
s1.span :span2 do |s2|
|
105
|
+
s2.column :col1
|
106
|
+
s2.column :col2
|
107
|
+
end
|
108
|
+
s1.span :span3 do |s3|
|
109
|
+
s3.column :col3
|
110
|
+
s3.column :col4
|
111
|
+
end
|
112
|
+
end
|
113
|
+
t.span :span4 do |s4|
|
114
|
+
s4.column :col5
|
115
|
+
s4.column :col6
|
116
|
+
end
|
117
|
+
t.column :col7, header_rowspan: 3
|
118
|
+
end
|
119
|
+
)
|
120
|
+
end
|
121
|
+
|
122
|
+
should "have 3 rows in thead" do
|
123
|
+
assert_select 'table thead tr', 3
|
124
|
+
end
|
125
|
+
|
126
|
+
should "have rowspan=3 in last th of first tr" do
|
127
|
+
th = css_select('table thead tr:first-child th:last-child').first
|
128
|
+
assert_equal '3', th.attributes['rowspan']
|
129
|
+
end
|
130
|
+
|
131
|
+
should "have 11 th elements in thead" do
|
132
|
+
assert_select 'table thead th', count: 11
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
if __FILE__== $0
|
2
|
+
require '../test_helper'
|
3
|
+
else
|
4
|
+
require 'test_helper'
|
5
|
+
end
|
6
|
+
|
7
|
+
class SpansTest < ActionView::TestCase
|
8
|
+
include EasyTable::Components::Spans
|
9
|
+
|
10
|
+
setup do
|
11
|
+
@node = Tree::TreeNode.new('root')
|
12
|
+
end
|
13
|
+
|
14
|
+
should "create a Span given title, a hash and a block" do
|
15
|
+
span('title', class: 'klazz') { |s| }
|
16
|
+
s = node.children.first.content
|
17
|
+
assert_equal 'title', s.instance_variable_get(:@title)
|
18
|
+
end
|
19
|
+
|
20
|
+
should "create a Span given title, label, a hash and a block" do
|
21
|
+
span('title', 'label', class: 'klazz') { |s| }
|
22
|
+
s = node.children.first.content
|
23
|
+
assert_equal 'title', s.instance_variable_get(:@title)
|
24
|
+
end
|
25
|
+
|
26
|
+
should "create a Span given a hash and a block" do
|
27
|
+
span(class: 'klazz') { |s| }
|
28
|
+
s = node.children.first.content
|
29
|
+
assert_nil s.instance_variable_get(:@title)
|
30
|
+
end
|
31
|
+
|
32
|
+
should "create a Span fiven only a block" do
|
33
|
+
span { |s| }
|
34
|
+
s = node.children.first.content
|
35
|
+
assert_nil s.instance_variable_get(:@title)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
require 'mocha'
|
6
|
+
require 'shoulda-context'
|
7
|
+
|
8
|
+
require 'active_model'
|
9
|
+
require 'action_controller'
|
10
|
+
require 'action_view'
|
11
|
+
require 'action_view/template'
|
12
|
+
|
13
|
+
# Rails 3.0.4 is missing this "deprecation" require.
|
14
|
+
require 'active_support/core_ext/module/deprecation'
|
15
|
+
require 'action_view/test_case'
|
16
|
+
|
17
|
+
module Rails
|
18
|
+
def self.env
|
19
|
+
ActiveSupport::StringInquirer.new("test")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
$:.unshift File.expand_path("../../lib", __FILE__)
|
24
|
+
require 'easy_table'
|
25
|
+
|
26
|
+
I18n.default_locale = :en
|
27
|
+
|
28
|
+
class ActionView::TestCase
|
29
|
+
include EasyTable::ActionViewExtensions::TableHelper
|
30
|
+
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: easy_table
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jakub Głuszecki
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activemodel
|
16
|
+
requirement: &16553160 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *16553160
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: actionpack
|
27
|
+
requirement: &16552040 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *16552040
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rubytree
|
38
|
+
requirement: &16551480 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *16551480
|
47
|
+
description: HTML tables made easy (in Rails 3)
|
48
|
+
email:
|
49
|
+
- jakub.gluszecki@gmail.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- Gemfile
|
56
|
+
- LICENSE
|
57
|
+
- README.md
|
58
|
+
- Rakefile
|
59
|
+
- easy_table.gemspec
|
60
|
+
- lib/easy_table.rb
|
61
|
+
- lib/easy_table/action_view_extensions/table_helper.rb
|
62
|
+
- lib/easy_table/components/base.rb
|
63
|
+
- lib/easy_table/components/column.rb
|
64
|
+
- lib/easy_table/components/columns.rb
|
65
|
+
- lib/easy_table/components/span.rb
|
66
|
+
- lib/easy_table/components/spans.rb
|
67
|
+
- lib/easy_table/table_builder.rb
|
68
|
+
- lib/easy_table/version.rb
|
69
|
+
- test/action_view_extensions/table_helper_test.rb
|
70
|
+
- test/components/spans_test.rb
|
71
|
+
- test/table_builder_test.rb
|
72
|
+
- test/test_helper.rb
|
73
|
+
homepage: ''
|
74
|
+
licenses: []
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.8.15
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: HTML tables made easy (in Rails 3)
|
97
|
+
test_files:
|
98
|
+
- test/action_view_extensions/table_helper_test.rb
|
99
|
+
- test/components/spans_test.rb
|
100
|
+
- test/table_builder_test.rb
|
101
|
+
- test/test_helper.rb
|