tabula_rasa 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Code Climate](https://codeclimate.com/github/rsl/tabula_rasa.png)](https://codeclimate.com/github/rsl/tabula_rasa) [![Build Status](https://travis-ci.org/rsl/tabula_rasa.png)](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
|