tabletastic 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +169 -26
- data/VERSION +1 -1
- data/lib/tabletastic.rb +81 -34
- data/spec/tabletastic_spec.rb +47 -4
- data/tabletastic.gemspec +56 -0
- metadata +3 -2
data/README.rdoc
CHANGED
@@ -4,46 +4,189 @@ Inspired by the projects table_builder and formtastic,
|
|
4
4
|
I realized how often I created tables for my active record collections.
|
5
5
|
This is my attempt to simply this (the default scaffold):
|
6
6
|
|
7
|
-
|
7
|
+
<table>
|
8
|
+
<tr>
|
9
|
+
<th>Title</th>
|
10
|
+
<th>Body</th>
|
11
|
+
<th>Author Id</th>
|
12
|
+
</tr>
|
13
|
+
<% for post in @posts %>
|
8
14
|
<tr>
|
9
|
-
<
|
10
|
-
<
|
11
|
-
<
|
12
|
-
|
13
|
-
|
14
|
-
<
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
<td><%=h author.name %></td>
|
19
|
-
<td><%= link_to "Show", post %></td>
|
20
|
-
<td><%= link_to "Edit", edit_post_path(post) %></td>
|
21
|
-
<td><%= link_to "Destroy", post, :confirm => 'Are you sure?', :method => :delete %></td>
|
22
|
-
</tr>
|
23
|
-
<% end %>
|
24
|
-
</table>
|
15
|
+
<td><%=h post.title %></td>
|
16
|
+
<td><%=h post.body %></td>
|
17
|
+
<td><%=h post.author_id %></td>
|
18
|
+
<td><%= link_to "Show", post %></td>
|
19
|
+
<td><%= link_to "Edit", edit_post_path(post) %></td>
|
20
|
+
<td><%= link_to "Destroy", post, :confirm => 'Are you sure?', :method => :delete %></td>
|
21
|
+
</tr>
|
22
|
+
<% end %>
|
23
|
+
</table>
|
25
24
|
|
26
25
|
into this:
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
<% table_for(@posts) do |t| %>
|
28
|
+
<%= t.data :title, :body, :author %>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
and still output the same effective results, but with all the semantic
|
32
|
+
goodness that tabular data should have, i.e. a +<thead>+ and +<tbody>+ element.
|
31
33
|
|
32
34
|
|
33
35
|
== Warning
|
34
|
-
THIS PROJECT IS UNDER HEAVY DEVELOPMENT.
|
35
|
-
IT IS NOT RECOMMENDED FOR USE IN PRODUCTION APPLICATIONS
|
36
36
|
|
37
|
+
This project is still being actively developed. As such, future updates might not be backwards-compatible.
|
38
|
+
|
39
|
+
== Installation
|
40
|
+
|
41
|
+
In your Rails project, as a gem:
|
42
|
+
config.gem "tabletastic", :source => "http://gemcutter.org"
|
43
|
+
|
44
|
+
Or, for if you're behind the times, as a plugin:
|
45
|
+
script/plugin install git://github.com/jgdavey/tabletastic.git
|
46
|
+
|
47
|
+
|
48
|
+
== Usage
|
49
|
+
|
50
|
+
By default, you can just use the table_for method to build up your table.
|
51
|
+
Assuming you have a Post model with title and body, that belongs to an Author model with a name,
|
52
|
+
you can just use the helper. It will try to detect all content fields and belongs to associations.
|
53
|
+
|
54
|
+
In your view, simply calling:
|
55
|
+
|
56
|
+
<% table_for(@posts) do |t| %>
|
57
|
+
<%= t.data %>
|
58
|
+
<% end %>
|
59
|
+
|
60
|
+
will produce html like this:
|
61
|
+
|
62
|
+
<table id="posts">
|
63
|
+
<thead>
|
64
|
+
<tr>
|
65
|
+
<th>Title</th>
|
66
|
+
<th>Body</th>
|
67
|
+
<th>Author</th>
|
68
|
+
</tr>
|
69
|
+
</thead>
|
70
|
+
<tbody>
|
71
|
+
<tr class="post odd" id="post_1">
|
72
|
+
<td>Something</td>
|
73
|
+
<td>Lorem ipsum dolor sit amet consequat. Duis aute irure dolor.</td>
|
74
|
+
<td>Jim Beam</td>
|
75
|
+
</tr>
|
76
|
+
<tr class="post even" id="post_2">
|
77
|
+
<td>Second Post</td>
|
78
|
+
<td>This is the second post</td>
|
79
|
+
<td>Jack Daniels</td>
|
80
|
+
</tr>
|
81
|
+
<tr class="post odd" id="post_3">
|
82
|
+
<td>Something else</td>
|
83
|
+
<td>Blah!</td>
|
84
|
+
<td></td>
|
85
|
+
</tr>
|
86
|
+
</tbody>
|
87
|
+
</table>
|
88
|
+
|
89
|
+
|
90
|
+
To limit the fields, change the order, or to include fields that are excluded by default (such as created_at),
|
91
|
+
You can list methods to call on each resource:
|
92
|
+
|
93
|
+
<% table_for(@posts) do |t| %>
|
94
|
+
<%= t.data :author, :title, :created_at %>
|
95
|
+
<% end %>
|
96
|
+
|
97
|
+
will produce html like:
|
98
|
+
|
99
|
+
<table id="posts">
|
100
|
+
<thead>
|
101
|
+
<tr>
|
102
|
+
<th>Author</th>
|
103
|
+
<th>Title</th>
|
104
|
+
<th>Created at</th>
|
105
|
+
</tr>
|
106
|
+
</thead>
|
107
|
+
<tbody>
|
108
|
+
<tr id="post_1" class="post odd">
|
109
|
+
<td>Jim Beam</td>
|
110
|
+
<td>Something</td>
|
111
|
+
<td>2009-11-15 02:42:48 UTC</td>
|
112
|
+
</tr>
|
113
|
+
<tr id="post_2" class="post even">
|
114
|
+
<td>Jack Daniels</td>
|
115
|
+
<td>Second Post</td>
|
116
|
+
<td>2009-11-16 00:11:00 UTC</td>
|
117
|
+
</tr>
|
118
|
+
<tr id="post_3" class="post odd">
|
119
|
+
<td></td>
|
120
|
+
<td>Something else</td>
|
121
|
+
<td>2009-11-16 00:11:30 UTC</td>
|
122
|
+
</tr>
|
123
|
+
</tbody>
|
124
|
+
</table>
|
125
|
+
|
126
|
+
For even greater flexibility, you can pass +data+ a block:
|
127
|
+
|
128
|
+
<% table_for(@posts) do |t| %>
|
129
|
+
<% t.data do %>
|
130
|
+
<%= t.cell(:title, :cell_html => {:class => "titlestring"}) %>
|
131
|
+
<%= t.cell(:body, :heading => "Content") {|p| truncate(p.body, 30)} %>
|
132
|
+
<%= t.cell(:author) {|p| p.author && link_to(p.author.name, p.author) } %>
|
133
|
+
<%= t.cell(:edit, :heading => '') {|p| link_to "Edit", edit_post_path(p) } %>
|
134
|
+
<% end -%>
|
135
|
+
<% end %>
|
136
|
+
|
137
|
+
will product html like:
|
138
|
+
|
139
|
+
<table id="posts">
|
140
|
+
<thead>
|
141
|
+
<tr>
|
142
|
+
<th>Title</th>
|
143
|
+
<th>Content</th>
|
144
|
+
<th>Author</th>
|
145
|
+
<th></th>
|
146
|
+
</tr>
|
147
|
+
</thead>
|
148
|
+
<tbody>
|
149
|
+
<tr class="post odd" id="post_1">
|
150
|
+
<td class="titlestring">Something</td>
|
151
|
+
<td>Lorem ipsum dolor sit amet,...</td>
|
152
|
+
<td>
|
153
|
+
<a href="/authors/1">Jim Bean</a>
|
154
|
+
</td>
|
155
|
+
<td>
|
156
|
+
<a href="/posts/1/edit">Edit</a>
|
157
|
+
</td>
|
158
|
+
</tr>
|
159
|
+
<tr class="post even" id="post_2">
|
160
|
+
<td class="titlestring">Second Post</td>
|
161
|
+
<td>This is the second post</td>
|
162
|
+
<td>
|
163
|
+
<a href="/authors/2">Jack Daniels</a>
|
164
|
+
</td>
|
165
|
+
<td>
|
166
|
+
<a href="/posts/2/edit">Edit</a>
|
167
|
+
</td>
|
168
|
+
</tr>
|
169
|
+
<tr class="post odd" id="post_3">
|
170
|
+
<td class="titlestring">Something else</td>
|
171
|
+
<td>Blah!</td>
|
172
|
+
<td></td>
|
173
|
+
<td>
|
174
|
+
<a href="/posts/3/edit">Edit</a>
|
175
|
+
</td>
|
176
|
+
</tr>
|
177
|
+
</tbody>
|
178
|
+
</table>
|
179
|
+
|
180
|
+
|
181
|
+
If it _still_ isn't flexible enough for your needs, it might be time to return to static html/erb.
|
37
182
|
|
38
183
|
== Note on Patches/Pull Requests
|
39
184
|
|
40
185
|
* Fork the project.
|
41
186
|
* Make your feature addition or bug fix.
|
42
|
-
* Add tests for it. This is important so I don't break it in a
|
43
|
-
future version unintentionally.
|
187
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
44
188
|
* Commit, do not mess with rakefile, version, or history.
|
45
|
-
(if you want to have your own version, that is fine but
|
46
|
-
bump version in a commit by itself I can ignore when I pull)
|
189
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
47
190
|
* Send me a pull request. Bonus points for topic branches.
|
48
191
|
|
49
192
|
== Copyright
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/lib/tabletastic.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Tabletastic
|
2
2
|
|
3
|
+
# returns and outputs a table for the given active record collection
|
3
4
|
def table_for(collection, *args)
|
4
5
|
options = args.extract_options!
|
5
6
|
options[:html] ||= {}
|
@@ -14,35 +15,64 @@ module Tabletastic
|
|
14
15
|
end
|
15
16
|
|
16
17
|
class TableBuilder
|
17
|
-
@@association_methods = %w[
|
18
|
+
@@association_methods = %w[display_name full_name name title username login value to_s]
|
19
|
+
attr_accessor :field_labels
|
18
20
|
|
19
21
|
def initialize(collection, template)
|
20
22
|
@collection, @template = collection, template
|
21
23
|
end
|
22
24
|
|
25
|
+
# builds up the fields that the table will include,
|
26
|
+
# returns table head and body with all data
|
23
27
|
def data(*args, &block)
|
24
28
|
if block_given?
|
25
29
|
yield self
|
26
|
-
@template.concat(
|
30
|
+
@template.concat(head)
|
27
31
|
@template.concat(body)
|
28
32
|
else
|
29
33
|
@fields = args unless args.empty?
|
30
|
-
|
34
|
+
@field_labels = fields.map { |f| f.to_s.humanize }
|
35
|
+
[head, body].join("")
|
31
36
|
end
|
32
37
|
end
|
33
38
|
|
34
|
-
def
|
39
|
+
def cell(*args, &block)
|
40
|
+
options = args.extract_options!
|
41
|
+
@field_labels ||= []
|
42
|
+
@fields ||= []
|
43
|
+
|
44
|
+
method_or_attribute = args.first.to_sym
|
45
|
+
|
46
|
+
if cell_html = options.delete(:cell_html)
|
47
|
+
@fields << [method_or_attribute, cell_html]
|
48
|
+
elsif block_given?
|
49
|
+
@fields << block.to_proc
|
50
|
+
else
|
51
|
+
@fields << method_or_attribute
|
52
|
+
end
|
53
|
+
|
54
|
+
if heading = options.delete(:heading)
|
55
|
+
@field_labels << heading
|
56
|
+
else
|
57
|
+
@field_labels << method_or_attribute.to_s.humanize
|
58
|
+
end
|
59
|
+
|
60
|
+
return "" # Since this will likely be called with <%= erb %>, this suppresses strange output
|
61
|
+
end
|
62
|
+
|
63
|
+
def head
|
64
|
+
@field_labels ||= fields
|
35
65
|
content_tag(:thead) do
|
36
66
|
header_row
|
37
67
|
end
|
38
68
|
end
|
39
69
|
|
40
70
|
def header_row
|
41
|
-
|
42
|
-
|
43
|
-
|
71
|
+
content_tag(:tr) do
|
72
|
+
@field_labels.inject("") do |result,field|
|
73
|
+
result += content_tag(:th, field)
|
74
|
+
end
|
44
75
|
end
|
45
|
-
output += "</tr>"
|
46
76
|
end
|
47
77
|
|
48
78
|
def body
|
@@ -61,49 +91,66 @@ module Tabletastic
|
|
61
91
|
end
|
62
92
|
|
63
93
|
def tds_for_row(record)
|
64
|
-
fields.inject("") do |cells,
|
65
|
-
|
94
|
+
fields.inject("") do |cells, field_or_array|
|
95
|
+
field = field_or_array
|
96
|
+
if field_or_array.is_a?(Array)
|
97
|
+
field = field_or_array.first
|
98
|
+
html_options = field_or_array.last
|
99
|
+
end
|
100
|
+
cells += content_tag(:td, cell_data(record, field), html_options)
|
66
101
|
end
|
67
102
|
end
|
68
103
|
|
69
|
-
def
|
70
|
-
|
104
|
+
def cell_data(record, method_or_attribute_or_proc)
|
105
|
+
# Get the attribute or association in question
|
106
|
+
result = send_or_call(record, method_or_attribute_or_proc)
|
107
|
+
# If we already have a string, just return it
|
71
108
|
return result if result.is_a?(String)
|
109
|
+
|
110
|
+
# If we don't have a string, its likely an association
|
111
|
+
# Try to detect which method to use for stringifying the attribute
|
72
112
|
to_string = detect_string_method(result)
|
73
113
|
result.send(to_string) if to_string
|
74
114
|
end
|
75
115
|
|
116
|
+
def fields
|
117
|
+
return @fields if defined?(@fields)
|
118
|
+
@fields = @collection.empty? ? [] : active_record_fields_for_object(@collection.first)
|
119
|
+
end
|
120
|
+
|
121
|
+
protected
|
122
|
+
|
76
123
|
def detect_string_method(association)
|
77
124
|
@@association_methods.detect { |method| association.respond_to?(method) }
|
78
125
|
end
|
79
126
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
127
|
+
|
128
|
+
def active_record_fields_for_object(obj)
|
129
|
+
# normal content columns
|
130
|
+
fields = obj.class.content_columns.map(&:name)
|
131
|
+
|
132
|
+
# active record associations
|
133
|
+
associations = obj.class.reflect_on_all_associations(:belongs_to) if obj.class.respond_to?(:reflect_on_all_associations)
|
134
|
+
if associations
|
135
|
+
associations = associations.map(&:name)
|
136
|
+
fields += associations
|
137
|
+
end
|
138
|
+
|
139
|
+
# remove utility columns by default
|
140
|
+
fields -= %w[created_at updated_at created_on updated_on lock_version version]
|
141
|
+
fields = fields.map(&:to_sym)
|
84
142
|
end
|
85
143
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
@fields = []
|
144
|
+
def send_or_call(object, duck)
|
145
|
+
if duck.is_a?(Proc)
|
146
|
+
duck.call(object)
|
90
147
|
else
|
91
|
-
object
|
92
|
-
associations = object.class.reflect_on_all_associations(:belongs_to) if object.class.respond_to?(:reflect_on_all_associations)
|
93
|
-
@fields = object.class.content_columns.map(&:name)
|
94
|
-
if associations
|
95
|
-
associations = associations.map(&:name)
|
96
|
-
@fields += associations
|
97
|
-
end
|
98
|
-
@fields -= %w[created_at updated_at created_on updated_on lock_version version]
|
99
|
-
@fields.map!(&:to_sym)
|
148
|
+
object.send(duck)
|
100
149
|
end
|
101
150
|
end
|
102
151
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
@template.content_tag(name, content, options, escape, &block)
|
107
|
-
end
|
152
|
+
def content_tag(name, content = nil, options = nil, escape = true, &block)
|
153
|
+
@template.content_tag(name, content, options, escape, &block)
|
154
|
+
end
|
108
155
|
end
|
109
156
|
end
|
data/spec/tabletastic_spec.rb
CHANGED
@@ -20,15 +20,15 @@ describe "Tabletastic#table_for" do
|
|
20
20
|
output_buffer.should have_tag("table")
|
21
21
|
end
|
22
22
|
|
23
|
-
context "
|
23
|
+
context "head and table body" do
|
24
24
|
before do
|
25
25
|
table_for([]) do |t|
|
26
|
-
concat(t.
|
26
|
+
concat(t.head)
|
27
27
|
concat(t.body)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
it "should build a basic table and
|
31
|
+
it "should build a basic table and head" do
|
32
32
|
output_buffer.should have_table_with_tag("thead")
|
33
33
|
end
|
34
34
|
|
@@ -69,7 +69,7 @@ describe "Tabletastic#table_for" do
|
|
69
69
|
output_buffer.should have_tag("table#posts")
|
70
70
|
end
|
71
71
|
|
72
|
-
it "should output
|
72
|
+
it "should output head" do
|
73
73
|
output_buffer.should have_table_with_tag("thead")
|
74
74
|
end
|
75
75
|
|
@@ -162,6 +162,49 @@ describe "Tabletastic#table_for" do
|
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
165
|
+
context "with custom cell options" do
|
166
|
+
before do
|
167
|
+
table_for(@posts) do |t|
|
168
|
+
t.data do
|
169
|
+
concat(t.cell(:title, :heading => "FooBar"))
|
170
|
+
concat(t.cell(:body, :cell_html => {:class => "batquux"}))
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should change the heading label for :heading option" do
|
176
|
+
output_buffer.should have_table_with_tag("th", "FooBar")
|
177
|
+
output_buffer.should have_table_with_tag("th", "Body")
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should pass :cell_html to the cell" do
|
181
|
+
output_buffer.should have_table_with_tag("td.batquux")
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context "with custom cell options" do
|
186
|
+
before do
|
187
|
+
table_for(@posts) do |t|
|
188
|
+
t.data do
|
189
|
+
concat(t.cell(:title) {|p| link_to p.title, "/" })
|
190
|
+
concat(t.cell(:body, :heading => "Content") {|p| p.body })
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
it "accepts a block as a lazy attribute" do
|
196
|
+
output_buffer.should have_table_with_tag("th:nth-child(1)", "Title")
|
197
|
+
output_buffer.should have_table_with_tag("td:nth-child(1)") do |td|
|
198
|
+
td.should have_tag("a", "The title of the post")
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
it "accepts a block as a lazy attribute (2)" do
|
203
|
+
output_buffer.should have_table_with_tag("th:nth-child(2)", "Content")
|
204
|
+
output_buffer.should have_table_with_tag("td:nth-child(2)", "Lorem ipsum")
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
165
208
|
context "and normal/association columns" do
|
166
209
|
before do
|
167
210
|
::Post.stub!(:reflect_on_all_associations).with(:belongs_to).and_return([@mock_reflection_belongs_to_author])
|
data/tabletastic.gemspec
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{tabletastic}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Joshua Davey"]
|
12
|
+
s.date = %q{2009-11-17}
|
13
|
+
s.description = %q{A table builder for active record collections that produces semantically rich and accessible markup}
|
14
|
+
s.email = %q{josh@joshuadavey.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/tabletastic.rb",
|
27
|
+
"rails/init.rb",
|
28
|
+
"spec/spec.opts",
|
29
|
+
"spec/spec_helper.rb",
|
30
|
+
"spec/tabletastic_spec.rb",
|
31
|
+
"tabletastic.gemspec"
|
32
|
+
]
|
33
|
+
s.homepage = %q{http://github.com/jgdavey/tabletastic}
|
34
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
35
|
+
s.require_paths = ["lib"]
|
36
|
+
s.rubygems_version = %q{1.3.5}
|
37
|
+
s.summary = %q{A smarter table builder for Rails collections}
|
38
|
+
s.test_files = [
|
39
|
+
"spec/spec_helper.rb",
|
40
|
+
"spec/tabletastic_spec.rb"
|
41
|
+
]
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
45
|
+
s.specification_version = 3
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
48
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
49
|
+
else
|
50
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
51
|
+
end
|
52
|
+
else
|
53
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tabletastic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Davey
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-17 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -43,6 +43,7 @@ files:
|
|
43
43
|
- spec/spec.opts
|
44
44
|
- spec/spec_helper.rb
|
45
45
|
- spec/tabletastic_spec.rb
|
46
|
+
- tabletastic.gemspec
|
46
47
|
has_rdoc: true
|
47
48
|
homepage: http://github.com/jgdavey/tabletastic
|
48
49
|
licenses: []
|