rails_table_for 0.2.0 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/{ruby.yml → test.yml} +9 -4
- data/.rubocop.yml +47 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +4 -2
- data/Gemfile.lock +83 -61
- data/Rakefile +5 -0
- data/bin/test +5 -3
- data/docs/Gemfile +8 -7
- data/docs/Gemfile.lock +10 -12
- data/docs/guides/auto-linking-rows.md +44 -0
- data/docs/guides/customizing-column-headers.md +36 -0
- data/docs/guides/customizing-row-values.md +41 -0
- data/docs/guides/getting-started.md +35 -0
- data/docs/guides/pagination.md +55 -0
- data/docs/index.md +14 -80
- data/lib/rails_table_for.rb +2 -0
- data/lib/rails_table_for/elements/block_column.rb +29 -0
- data/lib/rails_table_for/elements/column.rb +15 -0
- data/lib/rails_table_for/elements/field_column.rb +31 -0
- data/lib/rails_table_for/elements/table.rb +79 -0
- data/lib/rails_table_for/helpers/auto_link.rb +14 -0
- data/lib/rails_table_for/helpers/paginate.rb +62 -0
- data/lib/rails_table_for/railtie.rb +2 -0
- data/lib/rails_table_for/table_helper.rb +22 -10
- data/lib/rails_table_for/version.rb +3 -1
- data/rails_table_for.gemspec +2 -0
- metadata +58 -10
- data/.github/ISSUE_TEMPLATE/new-user-story.md +0 -20
- data/lib/rails_table_for/block_column.rb +0 -14
- data/lib/rails_table_for/column.rb +0 -5
- data/lib/rails_table_for/field_column.rb +0 -17
- data/lib/rails_table_for/table.rb +0 -61
- data/lib/tasks/rails_table_for_tasks.rake +0 -4
@@ -0,0 +1,44 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
title: rails_table_for
|
4
|
+
---
|
5
|
+
|
6
|
+
# Auto-linking Rows
|
7
|
+
|
8
|
+
With the last example, we displayed a link for each row by passing a block to the `column` method
|
9
|
+
and using `link_to`. This is a whole lot of extra code for something so simple. Let's see how we
|
10
|
+
can do something similar in a single line:
|
11
|
+
|
12
|
+
```
|
13
|
+
<%=
|
14
|
+
table_for @records do |table|
|
15
|
+
table.column :name, auto_link: true
|
16
|
+
end
|
17
|
+
%>
|
18
|
+
```
|
19
|
+
|
20
|
+
This will generate the following HTML:
|
21
|
+
|
22
|
+
```html
|
23
|
+
<table>
|
24
|
+
<thead>
|
25
|
+
<tr>
|
26
|
+
<th>Name</th>
|
27
|
+
</tr>
|
28
|
+
</thead>
|
29
|
+
<tbody>
|
30
|
+
<tr>
|
31
|
+
<td><a href="/records/1">Austin Roos</a></td>
|
32
|
+
</tr>
|
33
|
+
</tbody>
|
34
|
+
</table>
|
35
|
+
```
|
36
|
+
|
37
|
+
You can also pass a block to `column` still, whatever value you return will be placed inside
|
38
|
+
the anchor tag
|
39
|
+
|
40
|
+
If no route can be found for the record, a `NoMethodError` will be thrown.
|
41
|
+
|
42
|
+
Now that we've simplified the linking, we should move on to some more features to make the table
|
43
|
+
more user-friendly. It's likely that some collections are going to be much too large to display
|
44
|
+
on a single page, so let's try out [pagination](./pagination)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
title: rails_table_for
|
4
|
+
---
|
5
|
+
|
6
|
+
# Customizing Column Headers
|
7
|
+
|
8
|
+
A one-line table is a delight, but we're a bit limited by only getting values and headers directly from our models.
|
9
|
+
Let's start by customizing the column header. The `table_for` method accepts a block with a single `Table` argument.
|
10
|
+
This object has a single method (`.column`) that allows you some customization. You can use it like this:
|
11
|
+
|
12
|
+
```
|
13
|
+
<%= table_for @records do |table| %>
|
14
|
+
<% table.column :name, title: 'Naam' %>
|
15
|
+
<% end %>
|
16
|
+
```
|
17
|
+
|
18
|
+
The title of the column will now be `Naam` and the rest of the table will be the same as the first example:
|
19
|
+
```html
|
20
|
+
<table>
|
21
|
+
<thead>
|
22
|
+
<tr>
|
23
|
+
<th>Naam</th>
|
24
|
+
</tr>
|
25
|
+
</thead>
|
26
|
+
<tbody>
|
27
|
+
<tr>
|
28
|
+
<td>Austin Roos</td>
|
29
|
+
</tr>
|
30
|
+
...
|
31
|
+
</tbody>
|
32
|
+
</table>
|
33
|
+
```
|
34
|
+
|
35
|
+
So... we've got a pretty simple table here with our header in Dutch... there must be more right? Indeed, next let's see
|
36
|
+
how to do more than print out values directly off the model. Move on to [customizing row values](./customizing-row-values)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
title: rails_table_for
|
4
|
+
---
|
5
|
+
|
6
|
+
# Customizing Row Values
|
7
|
+
|
8
|
+
It's great that we can change the header on a column displaying a user's name, but we must be able to do more than just show
|
9
|
+
simple strings from our models in these rows, right? Right. You can pass a block to the `Table#column` method and return
|
10
|
+
anything your heart desires. Let's add a column that gives us a link to 'Show' the user.
|
11
|
+
|
12
|
+
```
|
13
|
+
<%=
|
14
|
+
table_for @records do |table|
|
15
|
+
table.column :name, title: 'Naam'
|
16
|
+
table.column title: 'Link' { |record| link_to 'Show', record }
|
17
|
+
end
|
18
|
+
%>
|
19
|
+
```
|
20
|
+
|
21
|
+
Assuming the route exists to show that record, this will generate HTML like this:
|
22
|
+
|
23
|
+
```html
|
24
|
+
<table>
|
25
|
+
<thead>
|
26
|
+
<tr>
|
27
|
+
<th>Naam</th>
|
28
|
+
<th>Link</th>
|
29
|
+
</tr>
|
30
|
+
</thead>
|
31
|
+
<tbody>
|
32
|
+
<tr>
|
33
|
+
<td>Austin Roos</td>
|
34
|
+
<td><a href="/records/1">Show</a></td>
|
35
|
+
</tr>
|
36
|
+
</tbody>
|
37
|
+
</table>
|
38
|
+
```
|
39
|
+
|
40
|
+
So... this gets us through most of the basics, but let's see if we can do things a little more simply. Check out
|
41
|
+
[auto-linking rows](./auto-linking-rows)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
title: rails_table_for
|
4
|
+
---
|
5
|
+
|
6
|
+
# Getting Started
|
7
|
+
|
8
|
+
For a simple table displaying some attributes of your ActiveRecord model, simply
|
9
|
+
call `table_for` with an ActiveRecord collection and an array of columns:
|
10
|
+
|
11
|
+
```
|
12
|
+
<%= table_for @records, columns: [:full_name] %>
|
13
|
+
```
|
14
|
+
|
15
|
+
The columns must correspond to methods/properties on the model class. The column header
|
16
|
+
will be the method/property name "humanized" (capitalized, split into words).
|
17
|
+
|
18
|
+
Example output:
|
19
|
+
```html
|
20
|
+
<table>
|
21
|
+
<thead>
|
22
|
+
<tr>
|
23
|
+
<th>Full Name</th>
|
24
|
+
</tr>
|
25
|
+
</thead>
|
26
|
+
<tbody>
|
27
|
+
<tr>
|
28
|
+
<td>Austin Roos</td>
|
29
|
+
</tr>
|
30
|
+
...
|
31
|
+
</tbody>
|
32
|
+
</table>
|
33
|
+
```
|
34
|
+
|
35
|
+
This is a good start, but surely you'd like to customize things a little bit. Move on to [customizing columns](./customizing-column-headers)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
title: rails_table_for
|
4
|
+
---
|
5
|
+
|
6
|
+
# Pagination (beta)
|
7
|
+
|
8
|
+
If you've made it this far, you know how to create some basic tables to present your data
|
9
|
+
in whatever way you see fit. Now you're so happy with your table that you want to present
|
10
|
+
50 million rows. This... is a little much for a single page. Enter pagination:
|
11
|
+
|
12
|
+
```
|
13
|
+
<%= table_for @records, columns: [:id, :name], page_size: 10 %>
|
14
|
+
```
|
15
|
+
|
16
|
+
and voila! you have a table showing only 10 rows per page as well as a set of links beneath
|
17
|
+
the table to take you to each page
|
18
|
+
|
19
|
+
```html
|
20
|
+
<div>
|
21
|
+
<table>
|
22
|
+
<thead>
|
23
|
+
<tr>
|
24
|
+
<th>Id</th>
|
25
|
+
<th>Name</th>
|
26
|
+
</tr>
|
27
|
+
</thead>
|
28
|
+
<tbody>
|
29
|
+
<tr>
|
30
|
+
<td>Austin Roos</td>
|
31
|
+
<td>1</td>
|
32
|
+
</tr>
|
33
|
+
...
|
34
|
+
</tbody>
|
35
|
+
</table>
|
36
|
+
<div class="pagination-links">
|
37
|
+
1
|
38
|
+
<a href="/users?page=2">2</a>
|
39
|
+
<a href="/users?page=3">3</a>
|
40
|
+
<a href="/users?page=4">4</a>
|
41
|
+
<a href="/users?page=5">5</a>
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
```
|
45
|
+
|
46
|
+
This feature is still in beta and there are some known limitations.
|
47
|
+
|
48
|
+
### Known Issues
|
49
|
+
|
50
|
+
If there are multiple tables on a single web page, the pages of the table will always be
|
51
|
+
synced because of the query parameter.
|
52
|
+
|
53
|
+
If the number of pages is very large, every pagination link is still shown instead of
|
54
|
+
something a bit more elegant like a few pages before and after the current one as well as
|
55
|
+
a link to first and last page
|
data/docs/index.md
CHANGED
@@ -3,6 +3,12 @@ layout: default
|
|
3
3
|
title: rails_table_for
|
4
4
|
---
|
5
5
|
|
6
|
+
# Introduciton
|
7
|
+
|
8
|
+
No more writing out dozens of <tr>, <th>, <td> elements. Write a few lines of ruby code (or even a single line) and
|
9
|
+
get a lovely little table generated for you. You can present data from your records directly with almost no work, or
|
10
|
+
do a little customization if you'd like something extra special. More features are coming soon, but pagination
|
11
|
+
already comes included (only if you want it).
|
6
12
|
|
7
13
|
# Installation
|
8
14
|
|
@@ -18,86 +24,14 @@ And then execute:
|
|
18
24
|
$ bundle
|
19
25
|
```
|
20
26
|
|
21
|
-
#
|
22
|
-
|
23
|
-
For the simplest table, just pass an ActiveRecord collection and an array of columns
|
24
|
-
```
|
25
|
-
<%= table_for @records, columns: [:name] %>
|
26
|
-
```
|
27
|
-
|
28
|
-
The columns must correspond to methods/properties on the record class. The column header
|
29
|
-
will be the method/property name "humanized".
|
30
|
-
|
31
|
-
Example output:
|
32
|
-
```html
|
33
|
-
<table>
|
34
|
-
<thead>
|
35
|
-
<tr>
|
36
|
-
<th>Name</th>
|
37
|
-
</tr>
|
38
|
-
</thead>
|
39
|
-
<tbody>
|
40
|
-
<tr>
|
41
|
-
<td>Austin</td>
|
42
|
-
</tr>
|
43
|
-
</tbody>
|
44
|
-
</table>
|
45
|
-
```
|
46
|
-
|
47
|
-
# Customize Column Headers
|
48
|
-
|
49
|
-
You can can change the default column headers by passing a block to `table_for` and using the `Table#column` method:
|
50
|
-
|
51
|
-
```
|
52
|
-
<%= table_for @records do |table| %>
|
53
|
-
<% table.column :name, title: 'Naam' %>
|
54
|
-
<% end %>
|
55
|
-
```
|
56
|
-
|
57
|
-
The title of the column will now be `Naam` and the rest of the table will be the same as the first example:
|
58
|
-
```html
|
59
|
-
<table>
|
60
|
-
<thead>
|
61
|
-
<tr>
|
62
|
-
<th>Naam</th>
|
63
|
-
</tr>
|
64
|
-
</thead>
|
65
|
-
<tbody>
|
66
|
-
<tr>
|
67
|
-
<td>Austin</td>
|
68
|
-
</tr>
|
69
|
-
</tbody>
|
70
|
-
</table>
|
71
|
-
```
|
27
|
+
# Code Examples
|
72
28
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
```
|
79
|
-
<%=
|
80
|
-
table_for @records do |table|
|
81
|
-
table.column title: 'Link' do |record|
|
82
|
-
link_to record.name, record
|
83
|
-
end
|
84
|
-
end
|
85
|
-
%>
|
86
|
-
```
|
29
|
+
- [Getting Started](./guides/getting-started) (a one-liner?!)
|
30
|
+
- [Customizing Column Headers](./guides/customizing-column-headers)
|
31
|
+
- [Customizing Row Values](./guides/customizing-row-values)
|
32
|
+
- [Auto-linking Rows](./guides/auto-linking-rows)
|
33
|
+
- [Pagination](./guides/pagination)
|
87
34
|
|
88
|
-
|
35
|
+
# Wanna Help?
|
89
36
|
|
90
|
-
|
91
|
-
<table>
|
92
|
-
<thead>
|
93
|
-
<tr>
|
94
|
-
<th>Link</th>
|
95
|
-
</tr>
|
96
|
-
</thead>
|
97
|
-
<tbody>
|
98
|
-
<tr>
|
99
|
-
<td><a href="/records/1">Record 1</a></td>
|
100
|
-
</tr>
|
101
|
-
</tbody>
|
102
|
-
</table>
|
103
|
-
```
|
37
|
+
Happily accepting bug reports, feature requests, and pull requests. Visit [https://github.com/acroos/rails_table_for](https://github.com/acroos/rails_table_for)
|
data/lib/rails_table_for.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_table_for/helpers/auto_link'
|
4
|
+
require 'rails_table_for/elements/column'
|
5
|
+
|
6
|
+
module RailsTableFor
|
7
|
+
module Elements
|
8
|
+
class BlockColumn
|
9
|
+
include ActionView::Helpers::TagHelper
|
10
|
+
include Helpers::AutoLink
|
11
|
+
include Column
|
12
|
+
|
13
|
+
attr_reader :block, :title, :auto_link_enabled
|
14
|
+
private :block, :title, :auto_link_enabled
|
15
|
+
|
16
|
+
def initialize(block, **options)
|
17
|
+
@block = block
|
18
|
+
@title = options[:title]
|
19
|
+
@auto_link_enabled = options[:auto_link] || false
|
20
|
+
end
|
21
|
+
|
22
|
+
def td(record)
|
23
|
+
text = block.call(record)
|
24
|
+
content = auto_link_enabled ? auto_link(record, text) : text
|
25
|
+
content_tag :td, content
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_table_for/helpers/auto_link'
|
4
|
+
require 'rails_table_for/elements/column'
|
5
|
+
|
6
|
+
module RailsTableFor
|
7
|
+
module Elements
|
8
|
+
class FieldColumn
|
9
|
+
include ActionView::Helpers::TagHelper
|
10
|
+
include Helpers::AutoLink
|
11
|
+
include Column
|
12
|
+
|
13
|
+
attr_reader :field, :title, :auto_link_enabled
|
14
|
+
private :field, :title, :auto_link_enabled
|
15
|
+
|
16
|
+
def initialize(field, **options)
|
17
|
+
raise('Field cannot be nil', ArgumentError) if field.nil?
|
18
|
+
|
19
|
+
@field = field
|
20
|
+
@title = options[:title] || field.to_s.humanize
|
21
|
+
@auto_link_enabled = options[:auto_link] || false
|
22
|
+
end
|
23
|
+
|
24
|
+
def td(record)
|
25
|
+
text = record.send(field)
|
26
|
+
content = auto_link_enabled ? auto_link(record, text) : text
|
27
|
+
content_tag :td, content
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_table_for/elements/block_column'
|
4
|
+
require 'rails_table_for/elements/field_column'
|
5
|
+
require 'rails_table_for/helpers/paginate'
|
6
|
+
|
7
|
+
module RailsTableFor
|
8
|
+
module Elements
|
9
|
+
class Table
|
10
|
+
include Helpers::Paginate
|
11
|
+
include ActionView::Helpers::TagHelper
|
12
|
+
|
13
|
+
attr_accessor :columns, :output_buffer, :page_size, :record_count, :records, :request_params,
|
14
|
+
:request_path
|
15
|
+
private :columns, :page_size, :record_count, :records, :request_params, :request_path
|
16
|
+
|
17
|
+
def initialize(records, **options)
|
18
|
+
@records = records
|
19
|
+
@record_count = records.count
|
20
|
+
@columns = []
|
21
|
+
options[:columns]&.each { |field| column(field) }
|
22
|
+
@page_size = options[:page_size]
|
23
|
+
@request_path = options[:request_path]
|
24
|
+
@request_params = options[:request_params]
|
25
|
+
end
|
26
|
+
|
27
|
+
def column(field = nil, **options, &block)
|
28
|
+
if block_given?
|
29
|
+
columns << BlockColumn.new(block, options)
|
30
|
+
elsif field
|
31
|
+
columns << FieldColumn.new(field, options)
|
32
|
+
else
|
33
|
+
raise 'Must provide either field or block'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
return '' if record_count.zero?
|
39
|
+
return '' if columns.empty?
|
40
|
+
|
41
|
+
draw
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def draw
|
47
|
+
content_tag :div do
|
48
|
+
table + pagination_links
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def table
|
53
|
+
content_tag :table do
|
54
|
+
head + body
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def head
|
59
|
+
content_tag :thead do
|
60
|
+
content_tag :tr do
|
61
|
+
columns.map(&:th).join.html_safe
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def body
|
67
|
+
content_tag :tbody do
|
68
|
+
current_page_records.map { |record| body_row(record) }.join.html_safe
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def body_row(record)
|
73
|
+
content_tag :tr do
|
74
|
+
columns.map { |column| column.td(record) }.join.html_safe
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|