table_helper 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +19 -0
- data/MIT-LICENSE +20 -0
- data/README +161 -0
- data/Rakefile +80 -0
- data/init.rb +1 -0
- data/lib/table_helper/body.rb +119 -0
- data/lib/table_helper/body_row.rb +86 -0
- data/lib/table_helper/cell.rb +51 -0
- data/lib/table_helper/collection_table.rb +60 -0
- data/lib/table_helper/footer.rb +47 -0
- data/lib/table_helper/header.rb +125 -0
- data/lib/table_helper/html_element.rb +46 -0
- data/lib/table_helper/row.rb +72 -0
- data/lib/table_helper.rb +182 -0
- data/test/body_row_test.rb +105 -0
- data/test/body_test.rb +271 -0
- data/test/cell_test.rb +52 -0
- data/test/collection_table_test.rb +254 -0
- data/test/footer_test.rb +72 -0
- data/test/header_test.rb +210 -0
- data/test/html_element_test.rb +74 -0
- data/test/row_test.rb +115 -0
- data/test/table_helper_test.rb +37 -0
- data/test/test_helper.rb +14 -0
- metadata +85 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
module PluginAWeek #:nodoc:
|
2
|
+
module TableHelper
|
3
|
+
# Represents a single cell within a table. This can either be a regular
|
4
|
+
# data cell (td) or a header cell (th). By default, all cells will have
|
5
|
+
# their column name appended to the cell's class attribute.
|
6
|
+
#
|
7
|
+
# == Creating data cells
|
8
|
+
#
|
9
|
+
# Cell.new(:author, 'John Doe').build
|
10
|
+
#
|
11
|
+
# ...would generate the following tag:
|
12
|
+
#
|
13
|
+
# <td class="author">John Doe</td>
|
14
|
+
#
|
15
|
+
# == Creating header cells
|
16
|
+
#
|
17
|
+
# c = Cell.new(:author, 'Author Name')
|
18
|
+
# c.content_type = :header
|
19
|
+
# c.build
|
20
|
+
#
|
21
|
+
# ...would generate the following tag:
|
22
|
+
#
|
23
|
+
# <th class="author">Author Name</th>
|
24
|
+
class Cell < HtmlElement
|
25
|
+
def initialize(class_name, content = class_name.to_s.titleize, html_options = {}) #:nodoc
|
26
|
+
super(html_options)
|
27
|
+
|
28
|
+
@content = content
|
29
|
+
@html_options[:class] = ("#{class_name} " + @html_options[:class].to_s).strip if class_name
|
30
|
+
|
31
|
+
self.content_type = :data
|
32
|
+
end
|
33
|
+
|
34
|
+
# Indicates what type of content will be stored in this cell. This can
|
35
|
+
# either be set to either :data or :header.
|
36
|
+
def content_type=(value)
|
37
|
+
raise ArgumentError, "content_type must be set to :data or :header, was: #{value.inspect}" if ![:data, :header].include?(value)
|
38
|
+
@content_type = value
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def tag_name
|
43
|
+
@content_type == :data ? 'td' : 'th'
|
44
|
+
end
|
45
|
+
|
46
|
+
def content
|
47
|
+
@content
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'table_helper/html_element'
|
2
|
+
require 'table_helper/header'
|
3
|
+
require 'table_helper/body'
|
4
|
+
require 'table_helper/footer'
|
5
|
+
|
6
|
+
module PluginAWeek #:nodoc:
|
7
|
+
module TableHelper
|
8
|
+
# Represents a table that is displaying data for multiple objects within
|
9
|
+
# a collection.
|
10
|
+
class CollectionTable < HtmlElement
|
11
|
+
def initialize(collection, options = {}, html_options = {}) #:nodoc:
|
12
|
+
super(html_options)
|
13
|
+
|
14
|
+
options.assert_valid_keys(
|
15
|
+
:class,
|
16
|
+
:footer,
|
17
|
+
:header
|
18
|
+
)
|
19
|
+
@options = options.reverse_merge(
|
20
|
+
:header => true,
|
21
|
+
:footer => false
|
22
|
+
)
|
23
|
+
|
24
|
+
@html_options.reverse_merge!(
|
25
|
+
:cellspacing => '0',
|
26
|
+
:cellpadding => '0'
|
27
|
+
)
|
28
|
+
|
29
|
+
@header = Header.new(collection, options[:class])
|
30
|
+
@body = Body.new(collection, @header)
|
31
|
+
@footer = Footer.new(collection)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Builds the table by rendering a header, body, and footer.
|
35
|
+
def build(&block)
|
36
|
+
@body.build # Build with the defaults
|
37
|
+
|
38
|
+
elements = []
|
39
|
+
elements << @header if @options[:header]
|
40
|
+
elements << @body
|
41
|
+
elements << @footer if @options[:footer]
|
42
|
+
|
43
|
+
yield *elements if block_given?
|
44
|
+
|
45
|
+
@content = ''
|
46
|
+
elements.each {|element| @content << element.html}
|
47
|
+
@content
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def tag_name
|
52
|
+
'table'
|
53
|
+
end
|
54
|
+
|
55
|
+
def content
|
56
|
+
@content
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'table_helper/row'
|
2
|
+
|
3
|
+
module PluginAWeek #:nodoc:
|
4
|
+
module TableHelper
|
5
|
+
# Represents the header of the table. In HTML, you can think of this as
|
6
|
+
# the tfoot tag of the table.
|
7
|
+
class Footer < HtmlElement
|
8
|
+
# The actual footer row
|
9
|
+
attr_reader :row
|
10
|
+
|
11
|
+
delegate :cell,
|
12
|
+
:to => :row
|
13
|
+
|
14
|
+
# Whether or not the footer should be hidden when the collection is
|
15
|
+
# empty. Default is true.
|
16
|
+
attr_accessor :hide_when_empty
|
17
|
+
|
18
|
+
def initialize(collection) #:nodoc:
|
19
|
+
super()
|
20
|
+
|
21
|
+
@collection = collection
|
22
|
+
@row = Row.new
|
23
|
+
@hide_when_empty = true
|
24
|
+
end
|
25
|
+
|
26
|
+
def html #:nodoc:
|
27
|
+
html_options = @html_options.dup
|
28
|
+
html_options[:style] = 'display: none;' if @collection.empty? && hide_when_empty
|
29
|
+
|
30
|
+
content_tag(tag_name, content, html_options)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def tag_name
|
35
|
+
'tfoot'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Generates the html for the footer. The footer generally consists of a
|
39
|
+
# summary of the data in the body. This row will be wrapped inside of
|
40
|
+
# a tfoot tag. If the collection is empty and hide_when_empty was set
|
41
|
+
# to true, then the footer will be hidden.
|
42
|
+
def content
|
43
|
+
@row.html
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'table_helper/row'
|
2
|
+
|
3
|
+
module PluginAWeek #:nodoc:
|
4
|
+
module TableHelper
|
5
|
+
# Represents the header of the table. In HTML, you can think of this as
|
6
|
+
# the <thead> tag of the table.
|
7
|
+
class Header < HtmlElement
|
8
|
+
# The actual header row
|
9
|
+
attr_reader :row
|
10
|
+
|
11
|
+
# Whether or not the header should be hidden when the collection is
|
12
|
+
# empty. Default is true.
|
13
|
+
attr_accessor :hide_when_empty
|
14
|
+
|
15
|
+
# Creates a new header for a collection that contains objects of the
|
16
|
+
# given class.
|
17
|
+
#
|
18
|
+
# If the class is known, then the header will be pre-filled with
|
19
|
+
# the columns defined in that class (assuming it's an ActiveRecord
|
20
|
+
# class).
|
21
|
+
def initialize(collection, klass = nil)
|
22
|
+
super()
|
23
|
+
|
24
|
+
@collection = collection
|
25
|
+
@row = Row.new
|
26
|
+
|
27
|
+
@hide_when_empty = true
|
28
|
+
@customized = true
|
29
|
+
|
30
|
+
# If we know what class the objects in the collection are and we can
|
31
|
+
# figure out what columns are defined in that class, then we can
|
32
|
+
# pre-fill the header with those columns so that the user doesn't
|
33
|
+
# have to
|
34
|
+
klass ||= class_for_collection(collection)
|
35
|
+
if klass && klass.respond_to?(:column_names)
|
36
|
+
klass.column_names.each {|name| column(name)}
|
37
|
+
@customized = false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Gets the names of all of the columns being displayed in the table
|
42
|
+
def column_names
|
43
|
+
row.cell_names
|
44
|
+
end
|
45
|
+
|
46
|
+
# Creates a new column with the specified caption. Columns must be
|
47
|
+
# defined in the order in which they will be rendered.
|
48
|
+
#
|
49
|
+
# The caption determines what will be displayed in each cell of the
|
50
|
+
# header (if the header is rendered). For example,
|
51
|
+
#
|
52
|
+
# header.column :title, 'The Title'
|
53
|
+
#
|
54
|
+
# ...will create a column the displays "The Title" in the cell.
|
55
|
+
#
|
56
|
+
# = Setting html options
|
57
|
+
#
|
58
|
+
# In addition to customizing the content of the column, you can also
|
59
|
+
# specify html options like so:
|
60
|
+
#
|
61
|
+
# header.column :title, 'The Title', :class => 'pretty'
|
62
|
+
def column(name, *args)
|
63
|
+
# Clear the header row if this is being customized by the user
|
64
|
+
if !@customized
|
65
|
+
@customized = true
|
66
|
+
|
67
|
+
# Remove all of the shortcut methods
|
68
|
+
column_names.each do |column|
|
69
|
+
klass = class << self; self; end
|
70
|
+
klass.class_eval do
|
71
|
+
remove_method(column)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
@row.clear
|
76
|
+
end
|
77
|
+
|
78
|
+
column = @row.cell(name, *args)
|
79
|
+
column.content_type = :header
|
80
|
+
column[:scope] ||= 'col'
|
81
|
+
|
82
|
+
# Define a shortcut method to the cell
|
83
|
+
name = name.to_s.gsub('-', '_')
|
84
|
+
unless respond_to?(name)
|
85
|
+
instance_eval <<-end_eval
|
86
|
+
def #{name}(*args)
|
87
|
+
if args.empty?
|
88
|
+
@row.#{name}
|
89
|
+
else
|
90
|
+
@row.#{name}(*args)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end_eval
|
94
|
+
end
|
95
|
+
|
96
|
+
column
|
97
|
+
end
|
98
|
+
|
99
|
+
# Creates and returns the generated html for the header
|
100
|
+
def html
|
101
|
+
html_options = @html_options.dup
|
102
|
+
html_options[:style] = 'display: none;' if @collection.empty? && hide_when_empty
|
103
|
+
|
104
|
+
content_tag(tag_name, content, html_options)
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def tag_name
|
109
|
+
'thead'
|
110
|
+
end
|
111
|
+
|
112
|
+
def content
|
113
|
+
@row.html
|
114
|
+
end
|
115
|
+
|
116
|
+
def class_for_collection(collection)
|
117
|
+
if collection.respond_to?(:proxy_reflection)
|
118
|
+
collection.proxy_reflection.klass
|
119
|
+
elsif !collection.empty?
|
120
|
+
collection.first.class
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module PluginAWeek #:nodoc:
|
2
|
+
module TableHelper
|
3
|
+
# Represents an HTML element
|
4
|
+
#
|
5
|
+
# == Modifying HTML options
|
6
|
+
#
|
7
|
+
# HTML options can normally be specified when creating the element.
|
8
|
+
# However, if they need to be modified after the element has been created,
|
9
|
+
# you can access the properties like so:
|
10
|
+
#
|
11
|
+
# r = Row.new
|
12
|
+
# r[:style] = 'display: none;'
|
13
|
+
#
|
14
|
+
# or for a cell:
|
15
|
+
#
|
16
|
+
# c = Cell.new
|
17
|
+
# c[:style] = 'display: none;'
|
18
|
+
class HtmlElement
|
19
|
+
include ActionView::Helpers::TagHelper
|
20
|
+
|
21
|
+
delegate :[],
|
22
|
+
:[]=,
|
23
|
+
:to => '@html_options'
|
24
|
+
|
25
|
+
def initialize(html_options = {}) #:nodoc:
|
26
|
+
@html_options = html_options.symbolize_keys
|
27
|
+
end
|
28
|
+
|
29
|
+
# Generates the html representing this element
|
30
|
+
def html
|
31
|
+
content_tag(tag_name, content, @html_options)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
# The name of the element tag to use (e.g. td, th, tr, etc.)
|
36
|
+
def tag_name
|
37
|
+
''
|
38
|
+
end
|
39
|
+
|
40
|
+
# The content that will be displayed inside of the tag
|
41
|
+
def content
|
42
|
+
''
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'table_helper/cell'
|
2
|
+
|
3
|
+
module PluginAWeek #:nodoc:
|
4
|
+
module TableHelper
|
5
|
+
# Represents a single row within a table. A row can consist of either
|
6
|
+
# data cells or header cells.
|
7
|
+
class Row < HtmlElement
|
8
|
+
def initialize #:nodoc:
|
9
|
+
super
|
10
|
+
|
11
|
+
@cells = ActiveSupport::OrderedHash.new
|
12
|
+
end
|
13
|
+
|
14
|
+
# Creates a new cell with the given name and generates shortcut
|
15
|
+
# accessors for the method.
|
16
|
+
def cell(name, *args)
|
17
|
+
name = name.to_s if name
|
18
|
+
|
19
|
+
cell = Cell.new(name, *args)
|
20
|
+
@cells[name] = cell
|
21
|
+
|
22
|
+
define_cell_accessor(name) if name && !respond_to?(name)
|
23
|
+
|
24
|
+
cell
|
25
|
+
end
|
26
|
+
|
27
|
+
# The names of all cells in this row
|
28
|
+
def cell_names
|
29
|
+
@cells.keys
|
30
|
+
end
|
31
|
+
|
32
|
+
# Clears all of the current cells from the row
|
33
|
+
def clear
|
34
|
+
cell_names.each do |name|
|
35
|
+
klass = class << self; self; end
|
36
|
+
klass.class_eval do
|
37
|
+
remove_method(name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
@cells.clear
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
# Defines the accessor method for the given cell name. For example, if
|
46
|
+
# a cell with the name :title was defined, then the cell would be able
|
47
|
+
# to be read and written like so:
|
48
|
+
#
|
49
|
+
# row.title #=> Accesses the title
|
50
|
+
# row.title "Page Title" #=> Creates a new cell with "Page Title" as the content
|
51
|
+
def define_cell_accessor(name)
|
52
|
+
instance_eval <<-end_eval
|
53
|
+
def #{name.gsub('-', '_')}(*args)
|
54
|
+
if args.empty?
|
55
|
+
@cells[#{name.inspect}]
|
56
|
+
else
|
57
|
+
cell(#{name.inspect}, *args)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end_eval
|
61
|
+
end
|
62
|
+
|
63
|
+
def tag_name
|
64
|
+
'tr'
|
65
|
+
end
|
66
|
+
|
67
|
+
def content
|
68
|
+
@cells.values.map(&:html).join
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/table_helper.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'table_helper/collection_table'
|
2
|
+
|
3
|
+
module PluginAWeek #:nodoc:
|
4
|
+
# Provides a set of methods for turning a collection into a table.
|
5
|
+
#
|
6
|
+
# == Basic Example
|
7
|
+
#
|
8
|
+
# This example shows the most basic usage of +collection_table+ which takes
|
9
|
+
# information about a collection, the objects in them, the columns defined
|
10
|
+
# for the class, and generates a table based on that.
|
11
|
+
#
|
12
|
+
# Support you have a table generated by a migration like so:
|
13
|
+
#
|
14
|
+
# class CreatePeople < ActiveRecord::Base
|
15
|
+
# def self.up
|
16
|
+
# create_table do |t|
|
17
|
+
# t.string :first_name
|
18
|
+
# t.string :last_name
|
19
|
+
# t.integer :company_id
|
20
|
+
# t.string :role
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# ...then invoking the helper:
|
26
|
+
#
|
27
|
+
# <%= collection_table Person.find(:all) %>
|
28
|
+
#
|
29
|
+
# ...is compiled to (formatted here for the sake of sanity):
|
30
|
+
#
|
31
|
+
# <table cellpadding="0" cellspacing="0">
|
32
|
+
# <thead>
|
33
|
+
# <tr>
|
34
|
+
# <th class="first_name" scope="col">First Name</th>
|
35
|
+
# <th class="last_name" scope="col">Last Name</th>
|
36
|
+
# <th class="company_id" scope="col">Company</th>
|
37
|
+
# <th class="role" scope="col">Role</th>
|
38
|
+
# </tr>
|
39
|
+
# </thead>
|
40
|
+
# <tbody>
|
41
|
+
# <tr class="row">
|
42
|
+
# <td class="first_name">John</td>
|
43
|
+
# <td class="last_name">Doe</td>
|
44
|
+
# <td class="company_id">1</td>
|
45
|
+
# <td class="role">President</td>
|
46
|
+
# </tr>
|
47
|
+
# <tr class="row">
|
48
|
+
# <td class="first_name">Jane</td>
|
49
|
+
# <td class="last_name">Doe</td>
|
50
|
+
# <td class="company_id">1</td>
|
51
|
+
# <td class="role">Vice-President</td>
|
52
|
+
# </tr>
|
53
|
+
# </tbody>
|
54
|
+
# <table>
|
55
|
+
#
|
56
|
+
# == Advanced Example
|
57
|
+
#
|
58
|
+
# This example below shows how +collection_table+ can be customized to show
|
59
|
+
# specific headers, content, and footers.
|
60
|
+
#
|
61
|
+
# <%=
|
62
|
+
# collection_table(@posts, {}, :id => 'posts', :class => 'summary') do |header, body|
|
63
|
+
# header.column :title
|
64
|
+
# header.column :category
|
65
|
+
# header.column :author
|
66
|
+
# header.column :publish_date, 'Date<br \>Published'
|
67
|
+
# header.column :num_comments, '# Comments'
|
68
|
+
# header.column :num_trackbacks, '# Trackbacks'
|
69
|
+
#
|
70
|
+
# body.alternate = true
|
71
|
+
# body.build do |row, post, index|
|
72
|
+
# row.category post.category.name
|
73
|
+
# row.author post.author.name
|
74
|
+
# row.publish_date time_ago_in_words(post.published_on)
|
75
|
+
# row.num_comments post.comments.empty? ? '-' : post.comments.size
|
76
|
+
# row.num_trackbacks post.trackbacks.empty? ? '-' : post.trackbacks.size
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
# %>
|
80
|
+
#
|
81
|
+
# ...is compiled to (formatted here for the sake of sanity):
|
82
|
+
#
|
83
|
+
# <table cellpadding="0" cellspacing="0" class="summary" id="posts">
|
84
|
+
# <thead>
|
85
|
+
# <tr>
|
86
|
+
# <th class="title" scope="col">Title</th>
|
87
|
+
# <th class="category" scope="col">Category</th>
|
88
|
+
# <th class="author" scope="col">Author</th>
|
89
|
+
# <th class="publish_date" scope="col">Date<br \>Published</th>
|
90
|
+
# <th class="num_comments" scope="col"># Comments</th>
|
91
|
+
# <th class="num_trackbacks" scope="col"># Trackbacks</th>
|
92
|
+
# </tr>
|
93
|
+
# </thead>
|
94
|
+
# <tbody class="alternate">
|
95
|
+
# <tr class="row">
|
96
|
+
# <td class="title">Open-source projects: The good, the bad, and the ugly</td>
|
97
|
+
# <td class="category">General</td>
|
98
|
+
# <td class="author">John Doe</td>
|
99
|
+
# <td class="publish_date">23 days</td>
|
100
|
+
# <td class="num_comments">-</td>
|
101
|
+
# <td class="num_trackbacks">-</td>
|
102
|
+
# </tr>
|
103
|
+
# <tr class="row alternate">
|
104
|
+
# <td class="title">5 reasons you should care about Rails</td>
|
105
|
+
# <td class="category">Rails</td><td class="author">John Q. Public</td>
|
106
|
+
# <td class="publish_date">21 days</td>
|
107
|
+
# <td class="num_comments">-</td>
|
108
|
+
# <td class="num_trackbacks">-</td>
|
109
|
+
# </tr>
|
110
|
+
# <tr class="row">
|
111
|
+
# <td class="title">Deprecation: Stop digging yourself a hole</td>
|
112
|
+
# <td class="category">Rails</td>
|
113
|
+
# <td class="author">Jane Doe</td>
|
114
|
+
# <td class="publish_date">17 days</td>
|
115
|
+
# <td class="num_comments">-</td>
|
116
|
+
# <td class="num_trackbacks">-</td>
|
117
|
+
# </tr>
|
118
|
+
# <tr class="row alternate">
|
119
|
+
# <td class="title">Jumpstart your Rails career at RailsConf 2007</td>
|
120
|
+
# <td class="category">Conferences</td>
|
121
|
+
# <td class="author">Jane Doe</td>
|
122
|
+
# <td class="publish_date">4 days</td>
|
123
|
+
# <td class="num_comments">-</td>
|
124
|
+
# <td class="num_trackbacks">-</td>
|
125
|
+
# </tr>
|
126
|
+
# <tr class="row">
|
127
|
+
# <td class="title">Getting some REST</td>
|
128
|
+
# <td class="category">Rails</td>
|
129
|
+
# <td class="author">John Doe</td>
|
130
|
+
# <td class="publish_date">about 18 hours</td>
|
131
|
+
# <td class="num_comments">-</td>
|
132
|
+
# <td class="num_trackbacks">-</td>
|
133
|
+
# </tr>
|
134
|
+
# </tbody>
|
135
|
+
# </table>
|
136
|
+
#
|
137
|
+
# == Creating footers
|
138
|
+
#
|
139
|
+
# Footers allow you to show some sort of summary information based on the
|
140
|
+
# data displayed in the body of the table. Below is an example:
|
141
|
+
#
|
142
|
+
# <%
|
143
|
+
# collection_table(@posts, :footer => true) do |header, body, footer|
|
144
|
+
# header.column :title
|
145
|
+
# header.column :category
|
146
|
+
# header.column :author
|
147
|
+
# header.column :publish_date, 'Date<br \>Published'
|
148
|
+
# header.column :num_comments, '# Comments'
|
149
|
+
# header.column :num_trackbacks, '# Trackbacks'
|
150
|
+
#
|
151
|
+
# body.alternate = true
|
152
|
+
# body.build do |row, post, index|
|
153
|
+
# row.category post.category.name
|
154
|
+
# row.author post.author.name
|
155
|
+
# row.publish_date time_ago_in_words(post.published_on)
|
156
|
+
# row.num_comments post.comments.empty? ? '-' : post.comments.size
|
157
|
+
# row.num_trackbacks post.trackbacks.empty? ? '-' : post.trackbacks.size
|
158
|
+
# end
|
159
|
+
#
|
160
|
+
# footer.cell :num_comments, @posts.inject(0) {|sum, post| sum += post.comments.size}
|
161
|
+
# footer.cell :num_trackbacks, @posts.inject(0) {|sum, post| sum += post.trackbacks.size}
|
162
|
+
# end
|
163
|
+
# %>
|
164
|
+
module TableHelper
|
165
|
+
# Creates a new table based on the given collection
|
166
|
+
#
|
167
|
+
# Configuration options:
|
168
|
+
#
|
169
|
+
# * +class+ - Specify the type of objects expected in the collection if it can't be guessed from its contents.
|
170
|
+
# * +header+ - Specify if a header (thead) should be built into the table. Default is true.
|
171
|
+
# * +footer+ - Specify if a footer (tfoot) should be built into the table. Default is false.
|
172
|
+
def collection_table(collection, options = {}, html_options = {}, &block)
|
173
|
+
table = CollectionTable.new(collection, options, html_options)
|
174
|
+
table.build(&block)
|
175
|
+
table.html
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
ActionController::Base.class_eval do
|
181
|
+
helper PluginAWeek::TableHelper
|
182
|
+
end
|