tabula_rasa 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/README.md +17 -2
- data/Rakefile +11 -1
- data/lib/tabula_rasa.rb +5 -3
- data/lib/tabula_rasa/base.rb +64 -0
- data/lib/tabula_rasa/column.rb +70 -0
- data/lib/tabula_rasa/helpers.rb +7 -0
- data/lib/tabula_rasa/version.rb +1 -1
- data/spec/config/active_record.rb +22 -0
- data/spec/config/spec.rb +27 -0
- data/spec/fixtures/survivors.yml +9 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/tabula_rasa/helper_body_spec.rb +173 -0
- data/spec/tabula_rasa/helper_head_spec.rb +138 -0
- data/spec/tabula_rasa/helper_integrated_spec.rb +50 -0
- data/spec/tabula_rasa/helper_table_spec.rb +93 -0
- data/tabula_rasa.gemspec +9 -2
- metadata +95 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77d9e0c24755a3555875efcb476b45574faff791
|
4
|
+
data.tar.gz: ab243bfe91d4bd59df5fc0e9ab9245b59f3d6b93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e27ca7c5d3570874a0c6ccf8262941d43814f3bca5e7bba1823f0551d8e129b9d424af58c58fcaa8df71ec5e45a48198ff76bf8099a315d7314c2bbbf473cee7
|
7
|
+
data.tar.gz: 68a9fa9df16526c3b8d3440721815163c2a6ac95acbbb6421b9ed848396ccd0f9690ffd67670011957d3853212bacff644cf380d36c4d5dc2fca93a163e71dd5
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
-
# TabulaRasa
|
1
|
+
# TabulaRasa [](https://codeclimate.com/github/rsl/tabula_rasa) [](https://travis-ci.org/rsl/tabula_rasa)
|
2
2
|
|
3
|
-
|
3
|
+
|
4
|
+
An opinionated yet simple table generator for Rails<sup>1</sup>.
|
5
|
+
|
6
|
+
TabulaRasa is designed to leverage ActiveRecord::Relation instances and conventions<sup>2</sup> to make table generation a snap but still readable and editable.
|
4
7
|
|
5
8
|
## Installation
|
6
9
|
|
@@ -27,3 +30,15 @@ TODO: Write usage instructions here
|
|
27
30
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
31
|
4. Push to the branch (`git push origin my-new-feature`)
|
29
32
|
5. Create new Pull Request
|
33
|
+
|
34
|
+
## TODO
|
35
|
+
|
36
|
+
* Write usage instructions
|
37
|
+
* Support for 'zebra-striping'
|
38
|
+
* TD dom_id and dom_class
|
39
|
+
|
40
|
+
## Footnotes
|
41
|
+
|
42
|
+
<sup>1</sup> TabulaRasa really only relies on ActiveRecord and ActionView/ActionPack so you could use in a non-Rails stack that had those two elements but it seemed silly to differentiate this in the summary sentence.
|
43
|
+
|
44
|
+
<sup>2</sup> These conventions may only be my own. Time will tell.
|
data/Rakefile
CHANGED
@@ -1 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Rake::TestTask.new('spec') do |t|
|
5
|
+
t.libs << 'lib' << 'spec'
|
6
|
+
t.pattern = 'spec/tabula_rasa/*_spec.rb'
|
7
|
+
t.verbose = true
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'Default: Run specs'
|
11
|
+
task :default => [:spec]
|
data/lib/tabula_rasa.rb
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'tabula_rasa/column'
|
2
|
+
|
3
|
+
module TabulaRasa
|
4
|
+
class Base
|
5
|
+
attr_reader :collection, :view, :klass, :columns, :options
|
6
|
+
|
7
|
+
delegate :capture, :content_tag, :safe_join, :truncate, to: :view
|
8
|
+
|
9
|
+
def initialize(collection, view, options = {}, &block)
|
10
|
+
raise ArgumentError, 'TabulaRasa only works on ActiveRecord Relation instances' unless collection.is_a?(ActiveRecord::Relation)
|
11
|
+
@collection = collection
|
12
|
+
@options = options
|
13
|
+
@view = view
|
14
|
+
@klass = collection.klass
|
15
|
+
@columns = []
|
16
|
+
yield self if block_given?
|
17
|
+
end
|
18
|
+
|
19
|
+
def render
|
20
|
+
return if columns.empty?
|
21
|
+
content_tag :table, content, table_options
|
22
|
+
end
|
23
|
+
|
24
|
+
def column(*args, &block)
|
25
|
+
@columns << Column.new(self, *args, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def content
|
31
|
+
safe_join [thead, tbody]
|
32
|
+
end
|
33
|
+
|
34
|
+
def thead
|
35
|
+
content_tag :thead, options[:head] do
|
36
|
+
content_tag :tr do
|
37
|
+
safe_join columns.map(&:head_content)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def tbody
|
43
|
+
content_tag :tbody, options[:body] do
|
44
|
+
collection.present? ? collection_body : empty_body
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def collection_body
|
49
|
+
rows = collection.map do |member|
|
50
|
+
content_tag :tr do
|
51
|
+
cells = columns.map do |column|
|
52
|
+
column.body_content_for member
|
53
|
+
end
|
54
|
+
safe_join cells
|
55
|
+
end
|
56
|
+
end
|
57
|
+
safe_join rows
|
58
|
+
end
|
59
|
+
|
60
|
+
def table_options
|
61
|
+
options.except :head, :body
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module TabulaRasa
|
2
|
+
class Column
|
3
|
+
delegate :capture, :content_tag, :truncate, to: :base
|
4
|
+
|
5
|
+
def initialize(base, *args, &block)
|
6
|
+
@base = base
|
7
|
+
@attribute = args.first
|
8
|
+
@options = args.extract_options!
|
9
|
+
yield self if block_given?
|
10
|
+
massage_options
|
11
|
+
ensure_valueable
|
12
|
+
end
|
13
|
+
|
14
|
+
def head_content
|
15
|
+
content_tag :th, head_value, options[:head]
|
16
|
+
end
|
17
|
+
|
18
|
+
def head
|
19
|
+
raise ArgumentError, "There's no need to pass a block for head. It's only evaluated once. Just set the head value via options or attribute [if appropriate]."
|
20
|
+
end
|
21
|
+
|
22
|
+
def body_content_for(instance)
|
23
|
+
content_tag :td, body_value_for(instance), options[:body]
|
24
|
+
end
|
25
|
+
|
26
|
+
def body(&block)
|
27
|
+
@body_value_option = block if block_given?
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :base, :attribute, :options, :head_value_option, :body_value_option
|
33
|
+
|
34
|
+
def ensure_valueable
|
35
|
+
ensure_head_valueable
|
36
|
+
ensure_body_valueable
|
37
|
+
end
|
38
|
+
|
39
|
+
def ensure_head_valueable
|
40
|
+
raise ArgumentError, 'Head value cannot be determined from arguments' unless head_value_option.present? || attribute.present?
|
41
|
+
end
|
42
|
+
|
43
|
+
def ensure_body_valueable
|
44
|
+
return if body_value_option.present? || base.collection.empty?
|
45
|
+
unless attribute.present? && base.collection.first.respond_to?(attribute)
|
46
|
+
raise ArgumentError, "Body value cannot be determined from arguments. #{base.klass} does not respond to #{attribute.inspect}."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def massage_options
|
51
|
+
@head_value_option = options[:head].is_a?(Hash) ? options[:head].delete(:value) : options.delete(:head)
|
52
|
+
# Allow for body_value_option having been set by body block. Do not allow overriding this!
|
53
|
+
@body_value_option ||= options[:body].is_a?(Hash) ? options[:body].delete(:value) : options.delete(:body)
|
54
|
+
end
|
55
|
+
|
56
|
+
def head_value
|
57
|
+
name = head_value_option || attribute
|
58
|
+
name.to_s.humanize.titleize
|
59
|
+
end
|
60
|
+
|
61
|
+
def body_value_for(instance)
|
62
|
+
value = body_value_option || instance.send(attribute)
|
63
|
+
if value.respond_to?(:call)
|
64
|
+
value.call(instance)
|
65
|
+
else
|
66
|
+
truncate value.to_s
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/tabula_rasa/version.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'active_record/fixtures'
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection :adapter => "sqlite3", :database => ":memory:"
|
4
|
+
ActiveRecord::Migration.verbose = false
|
5
|
+
ActiveRecord::Schema.define do
|
6
|
+
create_table :survivors, force: true do |t|
|
7
|
+
t.string :first_name, :last_name
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
ActiveRecord::Migration.verbose = true
|
12
|
+
|
13
|
+
class Survivor < ActiveRecord::Base
|
14
|
+
def display_name
|
15
|
+
[first_name, last_name].join ' '
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Manual fixture loading
|
20
|
+
Dir.glob('spec/fixtures/*.yml').each do |file|
|
21
|
+
ActiveRecord::FixtureSet.create_fixtures 'spec/fixtures', File.basename(file, '.yml')
|
22
|
+
end
|
data/spec/config/spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
class TabulaRasa::Spec < MiniTest::Spec
|
2
|
+
include ActionView::Helpers::CaptureHelper
|
3
|
+
include ActionView::Helpers::TagHelper
|
4
|
+
include ActionView::Helpers::TextHelper
|
5
|
+
include ActionView::Helpers::OutputSafetyHelper
|
6
|
+
include TabulaRasa::Helpers
|
7
|
+
|
8
|
+
attr_accessor :output_buffer
|
9
|
+
|
10
|
+
before do
|
11
|
+
@output_buffer = ActionView::OutputBuffer.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def extract_first(selector, html_string)
|
15
|
+
document_fragment_for(html_string).css(selector).first
|
16
|
+
end
|
17
|
+
|
18
|
+
def extract_all(selector, html_string)
|
19
|
+
document_fragment_for(html_string).css(selector)
|
20
|
+
end
|
21
|
+
|
22
|
+
def document_fragment_for(html_string)
|
23
|
+
Nokogiri::HTML::DocumentFragment.parse(html_string)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
MiniTest::Spec.register_spec_type /TabulaRasa/, TabulaRasa::Spec
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require 'minitest/spec'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
|
7
|
+
require 'active_support'
|
8
|
+
require 'active_record'
|
9
|
+
require 'active_record/fixtures'
|
10
|
+
require 'action_controller'
|
11
|
+
require 'action_view/helpers'
|
12
|
+
|
13
|
+
require 'nokogiri'
|
14
|
+
|
15
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
16
|
+
require 'tabula_rasa'
|
17
|
+
|
18
|
+
require 'config/active_record'
|
19
|
+
require 'config/spec'
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TabulaRasa::Helpers, 'Head Specs' do
|
4
|
+
before do
|
5
|
+
@survivors = Survivor.all
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'TBODY attributes' do
|
9
|
+
it 'sets no attributes by default' do
|
10
|
+
captured = capture do
|
11
|
+
tabula_rasa @survivors do |t|
|
12
|
+
t.column :first_name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
body = extract_first('table tbody', captured)
|
16
|
+
|
17
|
+
body.attributes.must_be_empty
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'can set attributes via options[:body] on main method' do
|
21
|
+
captured = capture do
|
22
|
+
tabula_rasa @survivors, body: {id: 'id_value', class: 'class_value', arbitrary: 'arbitrary_value'} do |t|
|
23
|
+
t.column :first_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
table = extract_first('table', captured)
|
27
|
+
body = extract_first('table tbody', captured)
|
28
|
+
|
29
|
+
body.attribute('id').value.must_equal 'id_value'
|
30
|
+
body.attribute('class').value.must_equal 'class_value'
|
31
|
+
body.attribute('arbitrary').value.must_equal 'arbitrary_value'
|
32
|
+
|
33
|
+
# Side test
|
34
|
+
table.attributes.must_be_empty
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# NOTE: For now, I don't see the point of adding attributes on TR element.
|
39
|
+
# I've had varying success styling on that and tend to style on the TH elements instead.
|
40
|
+
|
41
|
+
describe 'TD attributes' do
|
42
|
+
it 'sets no attributes by default' do
|
43
|
+
captured = capture do
|
44
|
+
tabula_rasa @survivors do |t|
|
45
|
+
t.column :first_name
|
46
|
+
end
|
47
|
+
end
|
48
|
+
cells = extract_all('table tbody td', captured)
|
49
|
+
|
50
|
+
cells.each do |cell|
|
51
|
+
cell.attributes.must_be_empty
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'can set attributes via options[:body] on internal column method' do
|
56
|
+
captured = capture do
|
57
|
+
tabula_rasa @survivors do |t|
|
58
|
+
t.column :first_name, id: 'id_value', class: 'class_value', arbitrary: 'arbitrary_value'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
table = extract_first('table', captured)
|
62
|
+
body = extract_first('table tbody', captured)
|
63
|
+
cells = extract_first('table tbody td', captured)
|
64
|
+
|
65
|
+
cells.each do |cell|
|
66
|
+
cell.attribute('id').value.must_equal 'id_value'
|
67
|
+
cell.attribute('class').value.must_equal 'class_value'
|
68
|
+
cell.attribute('arbitrary').value.must_equal 'arbitrary_value'
|
69
|
+
end
|
70
|
+
|
71
|
+
# Side tests
|
72
|
+
table.attributes.must_be_empty
|
73
|
+
body.attributes.must_be_empty
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'TD content' do
|
78
|
+
it 'uses the first argument by default' do
|
79
|
+
captured = capture do
|
80
|
+
tabula_rasa @survivors do |t|
|
81
|
+
t.column :first_name
|
82
|
+
end
|
83
|
+
end
|
84
|
+
cells = extract_all('table tbody td', captured)
|
85
|
+
|
86
|
+
cells.each_with_index do |cell, n|
|
87
|
+
cell.text.must_equal @survivors[n].first_name
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'can override first argument via options[:body] on internal column method' do
|
92
|
+
captured = capture do
|
93
|
+
tabula_rasa @survivors do |t|
|
94
|
+
t.column :first_name, body: 'Overridden Value'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
cells = extract_all('table tbody td', captured)
|
98
|
+
|
99
|
+
cells.each do |cell|
|
100
|
+
cell.text.must_equal 'Overridden Value'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'can override first argument via options[:body][:value] when setting attributes via options[:body] on internal column method' do
|
105
|
+
captured = capture do
|
106
|
+
tabula_rasa @survivors do |t|
|
107
|
+
t.column :first_name, body: {id: 'id_value', class: 'class_value', arbitrary: 'arbitrary_value', value: 'Overridden Value'}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
table = extract_first('table', captured)
|
111
|
+
body = extract_first('table tbody', captured)
|
112
|
+
cells = extract_all('table tbody td', captured)
|
113
|
+
|
114
|
+
cells.each do |cell|
|
115
|
+
cell.attribute('id').value.must_equal 'id_value'
|
116
|
+
cell.attribute('class').value.must_equal 'class_value'
|
117
|
+
cell.attribute('arbitrary').value.must_equal 'arbitrary_value'
|
118
|
+
|
119
|
+
cell.text.must_equal 'Overridden Value'
|
120
|
+
end
|
121
|
+
|
122
|
+
# Side tests
|
123
|
+
table.attributes.must_be_empty
|
124
|
+
body.attributes.must_be_empty
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'can override first argument via a Proc argument for internal column method' do
|
128
|
+
captured = capture do
|
129
|
+
tabula_rasa @survivors do |t|
|
130
|
+
t.column :whole_name do |c|
|
131
|
+
c.body do |instance|
|
132
|
+
"#{instance.first_name} #{instance.last_name}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
cells = extract_all('table tbody td', captured)
|
138
|
+
|
139
|
+
cells.each_with_index do |cell, n|
|
140
|
+
survivor = @survivors[n]
|
141
|
+
cell.text.must_equal "#{survivor.first_name} #{survivor.last_name}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'can override first argument via a Proc argument for internal column method while setting attributes via options[:body]' do
|
146
|
+
captured = capture do
|
147
|
+
tabula_rasa @survivors do |t|
|
148
|
+
t.column :whole_name, body: {id: 'id_value', class: 'class_value', arbitrary: 'arbitrary_value', value: 'Overridden Value'} do |c|
|
149
|
+
c.body do |instance|
|
150
|
+
"#{instance.first_name} #{instance.last_name}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
table = extract_first('table', captured)
|
156
|
+
body = extract_first('table tbody', captured)
|
157
|
+
cells = extract_all('table tbody td', captured)
|
158
|
+
|
159
|
+
cells.each_with_index do |cell, n|
|
160
|
+
survivor = @survivors[n]
|
161
|
+
cell.text.must_equal "#{survivor.first_name} #{survivor.last_name}"
|
162
|
+
|
163
|
+
cell.attribute('id').value.must_equal 'id_value'
|
164
|
+
cell.attribute('class').value.must_equal 'class_value'
|
165
|
+
cell.attribute('arbitrary').value.must_equal 'arbitrary_value'
|
166
|
+
end
|
167
|
+
|
168
|
+
# Side tests
|
169
|
+
table.attributes.must_be_empty
|
170
|
+
body.attributes.must_be_empty
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TabulaRasa::Helpers, 'Head Specs' do
|
4
|
+
before do
|
5
|
+
@survivors = Survivor.all
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'THEAD attributes' do
|
9
|
+
it 'sets no attributes by default' do
|
10
|
+
captured = capture do
|
11
|
+
tabula_rasa @survivors do |t|
|
12
|
+
t.column :first_name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
head = extract_first('table thead', captured)
|
16
|
+
|
17
|
+
head.attributes.must_be_empty
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'can set attributes via options[:head] on main method' do
|
21
|
+
captured = capture do
|
22
|
+
tabula_rasa @survivors, head: {id: 'id_value', class: 'class_value', arbitrary: 'arbitrary_value'} do |t|
|
23
|
+
t.column :first_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
table = extract_first('table', captured)
|
27
|
+
head = extract_first('table thead', captured)
|
28
|
+
|
29
|
+
head.attribute('id').value.must_equal 'id_value'
|
30
|
+
head.attribute('class').value.must_equal 'class_value'
|
31
|
+
head.attribute('arbitrary').value.must_equal 'arbitrary_value'
|
32
|
+
|
33
|
+
# Side test
|
34
|
+
table.attributes.must_be_empty
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# NOTE: For now, I don't see the point of adding attributes on TR element.
|
39
|
+
# I've had varying success styling on that and tend to style on the TH elements instead.
|
40
|
+
|
41
|
+
describe 'TH attributes' do
|
42
|
+
it 'sets no attributes by default' do
|
43
|
+
captured = capture do
|
44
|
+
tabula_rasa @survivors do |t|
|
45
|
+
t.column :first_name
|
46
|
+
end
|
47
|
+
end
|
48
|
+
cell = extract_first('table thead th', captured)
|
49
|
+
|
50
|
+
cell.attributes.must_be_empty
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'can set attributes via options[:head] on internal column method' do
|
54
|
+
captured = capture do
|
55
|
+
tabula_rasa @survivors do |t|
|
56
|
+
t.column :first_name, head: {id: 'id_value', class: 'class_value', arbitrary: 'arbitrary_value'}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
table = extract_first('table', captured)
|
60
|
+
head = extract_first('table thead', captured)
|
61
|
+
cell = extract_first('table thead th', captured)
|
62
|
+
|
63
|
+
cell.attribute('id').value.must_equal 'id_value'
|
64
|
+
cell.attribute('class').value.must_equal 'class_value'
|
65
|
+
cell.attribute('arbitrary').value.must_equal 'arbitrary_value'
|
66
|
+
|
67
|
+
# Side tests
|
68
|
+
table.attributes.must_be_empty
|
69
|
+
head.attributes.must_be_empty
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'TH content' do
|
74
|
+
it 'uses the first argument by default' do
|
75
|
+
captured = capture do
|
76
|
+
tabula_rasa @survivors do |t|
|
77
|
+
t.column :first_name
|
78
|
+
end
|
79
|
+
end
|
80
|
+
cell = extract_first('table thead th', captured)
|
81
|
+
|
82
|
+
cell.text.must_equal 'First Name'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'can override first argument via options[:head]' do
|
86
|
+
captured = capture do
|
87
|
+
tabula_rasa @survivors do |t|
|
88
|
+
t.column :first_name, head: 'Overridden Value'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
cell = extract_first('table thead th', captured)
|
92
|
+
|
93
|
+
cell.text.must_equal 'Overridden Value'
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'can override first argument via options[:head][:value] when setting attributes via options[:head]' do
|
97
|
+
captured = capture do
|
98
|
+
tabula_rasa @survivors do |t|
|
99
|
+
t.column :first_name, head: {id: 'id_value', class: 'class_value', arbitrary: 'arbitrary_value', value: 'Overridden Value'}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
table = extract_first('table', captured)
|
103
|
+
head = extract_first('table thead', captured)
|
104
|
+
cell = extract_first('table thead th', captured)
|
105
|
+
|
106
|
+
cell.attribute('id').value.must_equal 'id_value'
|
107
|
+
cell.attribute('class').value.must_equal 'class_value'
|
108
|
+
cell.attribute('arbitrary').value.must_equal 'arbitrary_value'
|
109
|
+
cell.attribute('value').must_be_nil
|
110
|
+
|
111
|
+
cell.text.must_equal 'Overridden Value'
|
112
|
+
|
113
|
+
# Side tests
|
114
|
+
table.attributes.must_be_empty
|
115
|
+
head.attributes.must_be_empty
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'raises ArgumentError if attempting to override content via a proc [as body can]' do
|
119
|
+
proc {
|
120
|
+
tabula_rasa @survivors do |t|
|
121
|
+
t.column :first_name do |c|
|
122
|
+
c.head do
|
123
|
+
# This will raise
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
}.must_raise(ArgumentError)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'raises ArgumentError if it cannot determine a value for head' do
|
131
|
+
proc {
|
132
|
+
tabula_rasa @survivors do |t|
|
133
|
+
t.column
|
134
|
+
end
|
135
|
+
}.must_raise(ArgumentError)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TabulaRasa::Helpers, 'Integrated [Head and Body] Specs' do
|
4
|
+
before do
|
5
|
+
@survivors = Survivor.all
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'can override head value while using attribute argument for body values' do
|
9
|
+
captured = capture do
|
10
|
+
tabula_rasa @survivors do |t|
|
11
|
+
t.column :first_name, head: 'First'
|
12
|
+
t.column :last_name, head: 'Last'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
head_cells = extract_all('table thead th', captured)
|
17
|
+
head_cells[0].text.must_equal 'First'
|
18
|
+
head_cells[1].text.must_equal 'Last'
|
19
|
+
|
20
|
+
body_rows = extract_all('table tbody tr', captured)
|
21
|
+
body_rows.each_with_index do |row, n|
|
22
|
+
survivor = @survivors[n]
|
23
|
+
cells = row.css('td')
|
24
|
+
cells[0].text.must_equal survivor.first_name
|
25
|
+
cells[1].text.must_equal survivor.last_name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'can override body values via proc while using attribute argument for head value' do
|
30
|
+
captured = capture do
|
31
|
+
tabula_rasa @survivors do |t|
|
32
|
+
t.column :whole_name do |c|
|
33
|
+
c.body do |instance|
|
34
|
+
"#{instance.first_name} #{instance.last_name}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
head_cell = extract_first('table thead th', captured)
|
41
|
+
head_cell.text.must_equal 'Whole Name'
|
42
|
+
|
43
|
+
body_rows = extract_all('table tbody tr', captured)
|
44
|
+
body_rows.each_with_index do |row, n|
|
45
|
+
survivor = @survivors[n]
|
46
|
+
cell = row.css('td').first
|
47
|
+
cell.text.must_equal "#{survivor.first_name} #{survivor.last_name}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TabulaRasa::Helpers, 'Table Specs' do
|
4
|
+
describe 'arguments' do
|
5
|
+
it 'raises ArgumentError if no arguments are passed' do
|
6
|
+
proc {
|
7
|
+
tabula_rasa
|
8
|
+
}.must_raise(ArgumentError)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'raises ArgumentError if collection is not ActiveRecord::Relation' do
|
12
|
+
proc {
|
13
|
+
tabula_rasa 'foo'
|
14
|
+
}.must_raise(ArgumentError)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns nothing when no block is given' do
|
18
|
+
captured = capture do
|
19
|
+
tabula_rasa Survivor.all
|
20
|
+
end
|
21
|
+
|
22
|
+
assert captured.blank?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'default table HTML' do
|
27
|
+
before do
|
28
|
+
captured = capture do
|
29
|
+
tabula_rasa Survivor.all do |t|
|
30
|
+
t.column :first_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
@doc = Nokogiri::HTML::DocumentFragment.parse(captured)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns well-formed HTML' do
|
37
|
+
@doc.errors.must_be_empty
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns a valid HTML table' do
|
41
|
+
@doc.css('table').size.must_equal 1
|
42
|
+
@doc.css('table').children.size.must_equal 2
|
43
|
+
@doc.css('table > thead').size.must_equal 1
|
44
|
+
@doc.css('table > thead').children.size.must_equal 1
|
45
|
+
@doc.css('table > thead > tr').size.must_equal 1
|
46
|
+
@doc.css('table > thead > tr').children.size.must_equal 1
|
47
|
+
@doc.css('table > thead > tr > th').size.must_equal 1
|
48
|
+
@doc.css('table > thead > tr > th').children.size.must_equal 1
|
49
|
+
# Assert the one child [from above] is just a text node
|
50
|
+
@doc.css('table > thead > tr > th').children.first.must_be :text?
|
51
|
+
@doc.css('table > tbody').size.must_equal 1
|
52
|
+
@doc.css('table > tbody').children.size.must_equal 3
|
53
|
+
@doc.css('table > tbody > tr').size.must_equal 3
|
54
|
+
@doc.css('table > tbody > tr').each do |row|
|
55
|
+
row.children.size.must_equal 1
|
56
|
+
row.css('td').must_equal row.children
|
57
|
+
row.css('td').children.size.must_equal 1
|
58
|
+
# Assert the one child [from above] is just a text node
|
59
|
+
row.css('td').children.first.must_be :text?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'TABLE attributes' do
|
64
|
+
before do
|
65
|
+
@survivors = Survivor.all
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'sets no attributes by default' do
|
69
|
+
captured = capture do
|
70
|
+
tabula_rasa @survivors do |t|
|
71
|
+
t.column :first_name
|
72
|
+
end
|
73
|
+
end
|
74
|
+
table = extract_first('table', captured)
|
75
|
+
|
76
|
+
table.attributes.must_be_empty
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'can set attributes via options on main method' do
|
80
|
+
captured = capture do
|
81
|
+
tabula_rasa @survivors, id: 'id_value', class: 'class_value', arbitrary: 'arbitrary_value' do |t|
|
82
|
+
t.column :first_name
|
83
|
+
end
|
84
|
+
end
|
85
|
+
table = extract_first('table', captured)
|
86
|
+
|
87
|
+
table.attribute('id').value.must_equal 'id_value'
|
88
|
+
table.attribute('class').value.must_equal 'class_value'
|
89
|
+
table.attribute('arbitrary').value.must_equal 'arbitrary_value'
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/tabula_rasa.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = TabulaRasa::VERSION
|
9
9
|
spec.authors = ["RSL"]
|
10
10
|
spec.email = ["sconds@gmail.com"]
|
11
|
-
spec.description = %q{An opinionated yet simple table generator for
|
12
|
-
spec.summary = %q{An opinionated yet simple table generator for
|
11
|
+
spec.description = %q{An opinionated yet simple table generator for Rails}
|
12
|
+
spec.summary = %q{An opinionated yet simple table generator for Rails}
|
13
13
|
spec.homepage = "https://github.com/rsl/tabula_rasa"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
@@ -20,4 +20,11 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "rake"
|
23
|
+
|
24
|
+
# My dependencies
|
25
|
+
spec.add_development_dependency 'minitest', '4.7.5'
|
26
|
+
spec.add_development_dependency 'actionpack', '4.0.0'
|
27
|
+
spec.add_development_dependency 'activerecord', '4.0.0'
|
28
|
+
spec.add_development_dependency 'nokogiri', '1.6.0'
|
29
|
+
spec.add_development_dependency 'sqlite3', '1.3.8'
|
23
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tabula_rasa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- RSL
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,7 +38,77 @@ dependencies:
|
|
38
38
|
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 4.7.5
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 4.7.5
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: actionpack
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 4.0.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 4.0.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activerecord
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 4.0.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 4.0.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: nokogiri
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.6.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.6.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: sqlite3
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.3.8
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.3.8
|
111
|
+
description: An opinionated yet simple table generator for Rails
|
42
112
|
email:
|
43
113
|
- sconds@gmail.com
|
44
114
|
executables: []
|
@@ -46,12 +116,24 @@ extensions: []
|
|
46
116
|
extra_rdoc_files: []
|
47
117
|
files:
|
48
118
|
- .gitignore
|
119
|
+
- .travis.yml
|
49
120
|
- Gemfile
|
50
121
|
- LICENSE.txt
|
51
122
|
- README.md
|
52
123
|
- Rakefile
|
53
124
|
- lib/tabula_rasa.rb
|
125
|
+
- lib/tabula_rasa/base.rb
|
126
|
+
- lib/tabula_rasa/column.rb
|
127
|
+
- lib/tabula_rasa/helpers.rb
|
54
128
|
- lib/tabula_rasa/version.rb
|
129
|
+
- spec/config/active_record.rb
|
130
|
+
- spec/config/spec.rb
|
131
|
+
- spec/fixtures/survivors.yml
|
132
|
+
- spec/spec_helper.rb
|
133
|
+
- spec/tabula_rasa/helper_body_spec.rb
|
134
|
+
- spec/tabula_rasa/helper_head_spec.rb
|
135
|
+
- spec/tabula_rasa/helper_integrated_spec.rb
|
136
|
+
- spec/tabula_rasa/helper_table_spec.rb
|
55
137
|
- tabula_rasa.gemspec
|
56
138
|
homepage: https://github.com/rsl/tabula_rasa
|
57
139
|
licenses:
|
@@ -76,5 +158,13 @@ rubyforge_project:
|
|
76
158
|
rubygems_version: 2.0.6
|
77
159
|
signing_key:
|
78
160
|
specification_version: 4
|
79
|
-
summary: An opinionated yet simple table generator for
|
80
|
-
test_files:
|
161
|
+
summary: An opinionated yet simple table generator for Rails
|
162
|
+
test_files:
|
163
|
+
- spec/config/active_record.rb
|
164
|
+
- spec/config/spec.rb
|
165
|
+
- spec/fixtures/survivors.yml
|
166
|
+
- spec/spec_helper.rb
|
167
|
+
- spec/tabula_rasa/helper_body_spec.rb
|
168
|
+
- spec/tabula_rasa/helper_head_spec.rb
|
169
|
+
- spec/tabula_rasa/helper_integrated_spec.rb
|
170
|
+
- spec/tabula_rasa/helper_table_spec.rb
|