table_go 0.1.9
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +101 -0
- data/LICENSE +22 -0
- data/README.md +86 -0
- data/Rakefile +2 -0
- data/lib/table_go/column.rb +46 -0
- data/lib/table_go/columns.rb +19 -0
- data/lib/table_go/formatter.rb +75 -0
- data/lib/table_go/helpers.rb +13 -0
- data/lib/table_go/railtie.rb +7 -0
- data/lib/table_go/renderers/csv_renderer.rb +21 -0
- data/lib/table_go/renderers/html_renderer.rb +48 -0
- data/lib/table_go/renderers/renderer_base.rb +88 -0
- data/lib/table_go/renderers.rb +7 -0
- data/lib/table_go/table.rb +32 -0
- data/lib/table_go/table_renderer.rb +19 -0
- data/lib/table_go/version.rb +3 -0
- data/lib/table_go.rb +32 -0
- data/spec/spec_helper.rb +35 -0
- data/spec/table_go/renderers/csv_renderer_spec.rb +96 -0
- data/spec/table_go/renderers/html_renderer_spec.rb +166 -0
- data/table_go.gemspec +26 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
data.tar.gz: 466df5bf94ac3a8efe5fe4c6d65d5e8ff45c5218
|
4
|
+
metadata.gz: 9b876f90007f7dde16692e8bb973b3115ed37966
|
5
|
+
SHA512:
|
6
|
+
data.tar.gz: 077564168872054f188cb8a5b7ba79a5eb424de627fcb6a522f342a1757e9b065af699e2a7862ef260bb0f85764241ae3df10bbf13de9f98ff2dcd30928a75fd
|
7
|
+
metadata.gz: 501d9814cbea4d8cc017b570e38ff3cf6784f0b4c3b02cc0ee67005b7c6168c16ce82750c5027d7e5ac7f7b6c7c35b5367e386182ea4b8210b76351a5f5e6de6
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--format documentation --color --fail-fast
|
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
gem 'rails'
|
3
|
+
gem 'fastercsv'
|
4
|
+
|
5
|
+
group :development, :test do
|
6
|
+
# gem 'sqlite3-ruby'
|
7
|
+
gem 'rspec-rails'
|
8
|
+
#gem 'pry-rails'
|
9
|
+
#gem 'ruby-debug'
|
10
|
+
end
|
11
|
+
|
12
|
+
group :test do
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
# Specify your gem's dependencies in table_go.gemspec
|
17
|
+
# gemspec
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
actionmailer (3.2.9)
|
5
|
+
actionpack (= 3.2.9)
|
6
|
+
mail (~> 2.4.4)
|
7
|
+
actionpack (3.2.9)
|
8
|
+
activemodel (= 3.2.9)
|
9
|
+
activesupport (= 3.2.9)
|
10
|
+
builder (~> 3.0.0)
|
11
|
+
erubis (~> 2.7.0)
|
12
|
+
journey (~> 1.0.4)
|
13
|
+
rack (~> 1.4.0)
|
14
|
+
rack-cache (~> 1.2)
|
15
|
+
rack-test (~> 0.6.1)
|
16
|
+
sprockets (~> 2.2.1)
|
17
|
+
activemodel (3.2.9)
|
18
|
+
activesupport (= 3.2.9)
|
19
|
+
builder (~> 3.0.0)
|
20
|
+
activerecord (3.2.9)
|
21
|
+
activemodel (= 3.2.9)
|
22
|
+
activesupport (= 3.2.9)
|
23
|
+
arel (~> 3.0.2)
|
24
|
+
tzinfo (~> 0.3.29)
|
25
|
+
activeresource (3.2.9)
|
26
|
+
activemodel (= 3.2.9)
|
27
|
+
activesupport (= 3.2.9)
|
28
|
+
activesupport (3.2.9)
|
29
|
+
i18n (~> 0.6)
|
30
|
+
multi_json (~> 1.0)
|
31
|
+
arel (3.0.2)
|
32
|
+
builder (3.0.4)
|
33
|
+
diff-lcs (1.1.3)
|
34
|
+
erubis (2.7.0)
|
35
|
+
fastercsv (1.5.4)
|
36
|
+
hike (1.2.1)
|
37
|
+
i18n (0.6.1)
|
38
|
+
journey (1.0.4)
|
39
|
+
json (1.7.5)
|
40
|
+
mail (2.4.4)
|
41
|
+
i18n (>= 0.4.0)
|
42
|
+
mime-types (~> 1.16)
|
43
|
+
treetop (~> 1.4.8)
|
44
|
+
mime-types (1.19)
|
45
|
+
multi_json (1.4.0)
|
46
|
+
polyglot (0.3.3)
|
47
|
+
rack (1.4.1)
|
48
|
+
rack-cache (1.2)
|
49
|
+
rack (>= 0.4)
|
50
|
+
rack-ssl (1.3.2)
|
51
|
+
rack
|
52
|
+
rack-test (0.6.2)
|
53
|
+
rack (>= 1.0)
|
54
|
+
rails (3.2.9)
|
55
|
+
actionmailer (= 3.2.9)
|
56
|
+
actionpack (= 3.2.9)
|
57
|
+
activerecord (= 3.2.9)
|
58
|
+
activeresource (= 3.2.9)
|
59
|
+
activesupport (= 3.2.9)
|
60
|
+
bundler (~> 1.0)
|
61
|
+
railties (= 3.2.9)
|
62
|
+
railties (3.2.9)
|
63
|
+
actionpack (= 3.2.9)
|
64
|
+
activesupport (= 3.2.9)
|
65
|
+
rack-ssl (~> 1.3.2)
|
66
|
+
rake (>= 0.8.7)
|
67
|
+
rdoc (~> 3.4)
|
68
|
+
thor (>= 0.14.6, < 2.0)
|
69
|
+
rake (10.0.2)
|
70
|
+
rdoc (3.12)
|
71
|
+
json (~> 1.4)
|
72
|
+
rspec-core (2.12.1)
|
73
|
+
rspec-expectations (2.12.0)
|
74
|
+
diff-lcs (~> 1.1.3)
|
75
|
+
rspec-mocks (2.12.0)
|
76
|
+
rspec-rails (2.12.0)
|
77
|
+
actionpack (>= 3.0)
|
78
|
+
activesupport (>= 3.0)
|
79
|
+
railties (>= 3.0)
|
80
|
+
rspec-core (~> 2.12.0)
|
81
|
+
rspec-expectations (~> 2.12.0)
|
82
|
+
rspec-mocks (~> 2.12.0)
|
83
|
+
sprockets (2.2.2)
|
84
|
+
hike (~> 1.2)
|
85
|
+
multi_json (~> 1.0)
|
86
|
+
rack (~> 1.0)
|
87
|
+
tilt (~> 1.1, != 1.3.0)
|
88
|
+
thor (0.16.0)
|
89
|
+
tilt (1.3.3)
|
90
|
+
treetop (1.4.12)
|
91
|
+
polyglot
|
92
|
+
polyglot (>= 0.3.1)
|
93
|
+
tzinfo (0.3.35)
|
94
|
+
|
95
|
+
PLATFORMS
|
96
|
+
ruby
|
97
|
+
|
98
|
+
DEPENDENCIES
|
99
|
+
fastercsv
|
100
|
+
rails
|
101
|
+
rspec-rails
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Lars Gollnow
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# TableGo
|
2
|
+
|
3
|
+
simple, flexible and fast html table generator
|
4
|
+
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'table_go'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install table_go
|
19
|
+
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
example in HAML
|
24
|
+
|
25
|
+
= table_go_for @orders, Order, :title => 'one Table',
|
26
|
+
:table_html => { :id => :the_table },
|
27
|
+
:row_html => { :class => lambda { cycle('even', 'odd') },
|
28
|
+
:id => lambda { |record| dom_id(record, :special) }} do |t|
|
29
|
+
|
30
|
+
- t.column :id,
|
31
|
+
:column_html => { :class => lambda { |record, column, value| value.even? ? :even : :odd } }
|
32
|
+
|
33
|
+
- t.column :my_type,
|
34
|
+
:send => :titleize
|
35
|
+
|
36
|
+
- t.column :vat,
|
37
|
+
:label => 'as percent',
|
38
|
+
:as => :percent
|
39
|
+
|
40
|
+
- t.column :price,
|
41
|
+
:label => 'as € currency',
|
42
|
+
:as => :currency
|
43
|
+
|
44
|
+
- t.column :date_of_order,
|
45
|
+
:header_html => { :class => :date, :style => :xyz, :id => :date_column },
|
46
|
+
:column_html => { :class => :date,
|
47
|
+
:style => :xyz,
|
48
|
+
:id => lambda { |record, column, value| "date_#{record.id}" }}
|
49
|
+
|
50
|
+
- t.column :date_of_order,
|
51
|
+
:as => :date,
|
52
|
+
:as_options => { :format => :short }
|
53
|
+
|
54
|
+
- t.column :date_of_order,
|
55
|
+
:label => 'with custom formatter',
|
56
|
+
:as => lambda { |value, record, column| value.to_s.reverse }
|
57
|
+
|
58
|
+
- t.column :date_of_order,
|
59
|
+
:label => 'with block level custom formatter' do |value, record, column|
|
60
|
+
%b do it
|
61
|
+
%br
|
62
|
+
= value
|
63
|
+
%b like u want
|
64
|
+
|
65
|
+
|
66
|
+
- t.column :xmas_bonus,
|
67
|
+
:as => :boolean,
|
68
|
+
:label => 'as boolean'
|
69
|
+
|
70
|
+
- t.column :customer,
|
71
|
+
:method => :name
|
72
|
+
|
73
|
+
|
74
|
+
## TODO:
|
75
|
+
|
76
|
+
- add sorting for column
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
## Contributing
|
81
|
+
|
82
|
+
1. Fork it
|
83
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
84
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
85
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
86
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module TableGo
|
2
|
+
class Column
|
3
|
+
attr_accessor :table, :name, :options, :block
|
4
|
+
|
5
|
+
def initialize(table, name, options = {}, &block)
|
6
|
+
@table, @name, @options, @block = table, name, options, block
|
7
|
+
end
|
8
|
+
|
9
|
+
def label
|
10
|
+
options[:label]
|
11
|
+
end
|
12
|
+
|
13
|
+
def as
|
14
|
+
options[:as]
|
15
|
+
end
|
16
|
+
|
17
|
+
def send
|
18
|
+
options[:send]
|
19
|
+
end
|
20
|
+
|
21
|
+
def as_options
|
22
|
+
options[:as_options] || {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def header_html
|
26
|
+
options[:header_html]
|
27
|
+
end
|
28
|
+
|
29
|
+
def column_html
|
30
|
+
options[:column_html]
|
31
|
+
end
|
32
|
+
|
33
|
+
def method
|
34
|
+
options[:method]
|
35
|
+
end
|
36
|
+
|
37
|
+
def human_attribute_name
|
38
|
+
if table.model_klass.respond_to?(:human_attribute_name)
|
39
|
+
table.model_klass.human_attribute_name(name).html_safe
|
40
|
+
else
|
41
|
+
name.to_s.humanize
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module TableGo
|
2
|
+
class Columns
|
3
|
+
include Enumerable
|
4
|
+
attr_accessor :table
|
5
|
+
|
6
|
+
def initialize(table)
|
7
|
+
@table, @columns = table, []
|
8
|
+
end
|
9
|
+
|
10
|
+
def column(name, options = {}, &block)
|
11
|
+
@columns << Column.new(table, name, options, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def each(&block)
|
15
|
+
@columns.each(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module TableGo
|
2
|
+
class Formatter
|
3
|
+
extend ActionView::Helpers::NumberHelper
|
4
|
+
|
5
|
+
class MissingFormatterError < StandardError; end
|
6
|
+
|
7
|
+
class_attribute :formatters
|
8
|
+
self.formatters = {}
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
formatters.store(:date,
|
13
|
+
lambda do |value, record, column|
|
14
|
+
value.present? ? I18n.l(value, :format => (column.as_options[:format] || :default)) : value
|
15
|
+
end
|
16
|
+
)
|
17
|
+
|
18
|
+
formatters.store(:datetime,
|
19
|
+
lambda do |value, record, column|
|
20
|
+
value.present? ? I18n.l(Time.parse(value.to_s).localtime, :format => (column.as_options[:format] || :default)) : value
|
21
|
+
end
|
22
|
+
)
|
23
|
+
|
24
|
+
formatters.store(:boolean,
|
25
|
+
lambda do |value, record, column|
|
26
|
+
if value == true
|
27
|
+
'✔'
|
28
|
+
elsif value == false
|
29
|
+
'✘'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
)
|
33
|
+
|
34
|
+
formatters.store(:percent,
|
35
|
+
lambda do |value, record, column|
|
36
|
+
number_to_percentage(value, column.as_options)
|
37
|
+
end
|
38
|
+
)
|
39
|
+
|
40
|
+
formatters.store(:currency,
|
41
|
+
lambda do |value, record, column|
|
42
|
+
number_to_currency(value, column.as_options)
|
43
|
+
end
|
44
|
+
)
|
45
|
+
|
46
|
+
formatters.store(:number,
|
47
|
+
lambda do |value, record, column|
|
48
|
+
number_with_delimiter(value, column.as_options)
|
49
|
+
end
|
50
|
+
)
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
def self.apply(formatter, record, column, value)
|
56
|
+
formatter_proc =
|
57
|
+
case formatter
|
58
|
+
when Symbol; formatters[formatter.to_sym]
|
59
|
+
when Proc; formatter
|
60
|
+
end
|
61
|
+
|
62
|
+
raise MissingFormatterError.new('formatter "%s" not found' % formatter) if formatter_proc.blank?
|
63
|
+
formatter_proc.call(value, record, column).to_s.html_safe
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.apply_send(formatter, record, column, value)
|
67
|
+
value.send(formatter).to_s.html_safe
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# when Time
|
75
|
+
# I18n.l(value.localtime, :format => :compact)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module TableGo
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
def table_go_for(collection, model_klass, options = {}, &block)
|
5
|
+
if request && request.format.csv?
|
6
|
+
capture { TableGo.render_csv(collection, model_klass, options, &block).html_safe }
|
7
|
+
else
|
8
|
+
capture { TableGo.render_html(collection, model_klass, self, options, &block) }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'fastercsv'
|
2
|
+
module TableGo
|
3
|
+
module Renderers
|
4
|
+
class CsvRenderer
|
5
|
+
include RendererBase
|
6
|
+
|
7
|
+
def render_template
|
8
|
+
::FasterCSV.generate(:col_sep => ";", :row_sep => "\n", :force_quotes => true, :quote_char => '"') do |csv|
|
9
|
+
csv << source_table.columns.map { |column| label_for_column(column) }
|
10
|
+
source_table.collection.each do |record|
|
11
|
+
csv << source_table.columns.map do |column|
|
12
|
+
value = value_from_record_by_column(record, column)
|
13
|
+
apply_formatter(record, column, value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module TableGo
|
2
|
+
module Renderers
|
3
|
+
class HtmlRenderer
|
4
|
+
include RendererBase
|
5
|
+
|
6
|
+
def render_template
|
7
|
+
template.content_tag :table, table_html do
|
8
|
+
template.concat template.content_tag(:caption, title) if title
|
9
|
+
template.concat table_head
|
10
|
+
template.concat table_body
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def table_head
|
15
|
+
template.content_tag :thead do
|
16
|
+
template.content_tag(:tr) do
|
17
|
+
source_table.columns.each do |column|
|
18
|
+
template.concat template.content_tag(:th, label_for_column(column), html_options_for_header(column))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def table_body
|
26
|
+
template.content_tag :tbody do
|
27
|
+
|
28
|
+
source_table.collection.each do |record|
|
29
|
+
tr = template.content_tag(:tr, html_options_for_row(record)) do
|
30
|
+
source_table.columns.each do |column|
|
31
|
+
value = value_from_record_by_column(record, column)
|
32
|
+
template.concat template.content_tag(:td, apply_formatter(record, column, value), html_options_for_cell(record, column, value))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
template.concat tr
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def table_foot
|
41
|
+
template.content_tag :tfoot do
|
42
|
+
template.content_tag :tr do
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module TableGo
|
2
|
+
module Renderers
|
3
|
+
module RendererBase
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include ActionView::Helpers::CaptureHelper
|
6
|
+
|
7
|
+
included do
|
8
|
+
attr_accessor :source_table, :title, :table_html, :row_html, :template
|
9
|
+
# attr_accessor :output_buffer
|
10
|
+
end
|
11
|
+
|
12
|
+
def apply_options(options)
|
13
|
+
self.title = options.delete(:title)
|
14
|
+
self.table_html = options.delete(:table_html)
|
15
|
+
self.row_html = options.delete(:row_html)
|
16
|
+
end
|
17
|
+
|
18
|
+
def render_template
|
19
|
+
raise ArgumentError.new('implement #render_template in concrete renderer')
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def label_for_column(column)
|
24
|
+
column.label || begin
|
25
|
+
if column.method && 1==3# reflection = source_table.model_klass.reflections[column.name]
|
26
|
+
reflection.klass.human_attribute_name(column.method).html_safe
|
27
|
+
# if column.method && reflection = source_table.model_klass.reflections[column.name]
|
28
|
+
# reflection.klass.human_attribute_name(column.method).html_safe
|
29
|
+
else
|
30
|
+
column.human_attribute_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def html_options_for_header(column)
|
36
|
+
{}.tap do |h|
|
37
|
+
(column.header_html || {}).each do |k, v|
|
38
|
+
h[k] = v.is_a?(Proc) ? v.call(column) : v
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def html_options_for_row(record)
|
44
|
+
{}.tap do |h|
|
45
|
+
(row_html || {}).each do |k, v|
|
46
|
+
h[k] = v.is_a?(Proc) ? v.call(record) : v
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def html_options_for_cell(record, column, value)
|
52
|
+
{}.tap do |h|
|
53
|
+
(column.column_html || {}).each do |k, v|
|
54
|
+
h[k] = v.is_a?(Proc) ? v.call(record, column, value) : v
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# def render_record(record, column)
|
60
|
+
# apply_formatter(record, column, value_from_record_by_column(record, column))
|
61
|
+
# end
|
62
|
+
|
63
|
+
def value_from_record_by_column(record, column)
|
64
|
+
if record.respond_to?(column.name)
|
65
|
+
value = record.send(column.name)
|
66
|
+
column.method ? value.send(column.method) : value
|
67
|
+
else
|
68
|
+
''
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def apply_formatter(record, column, value)
|
74
|
+
if formatter = column.as
|
75
|
+
Formatter.apply(formatter, record, column, value)
|
76
|
+
elsif formatter = column.send
|
77
|
+
Formatter.apply_send(formatter, record, column, value)
|
78
|
+
elsif formatter = column.block
|
79
|
+
Formatter.apply(formatter, record, column, value )
|
80
|
+
# capture { Formatter.apply(formatter, record, column, value )}
|
81
|
+
else
|
82
|
+
value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module TableGo
|
2
|
+
class Table
|
3
|
+
|
4
|
+
attr_accessor :collection, :model_klass, :columns
|
5
|
+
|
6
|
+
def initialize(collection, model_klass, &block)
|
7
|
+
@collection = collection
|
8
|
+
@model_klass = model_klass
|
9
|
+
@columns = Columns.new(self)
|
10
|
+
evaluate_dsl(block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def evaluate_dsl(block)
|
14
|
+
if block
|
15
|
+
block.call(@columns)
|
16
|
+
else
|
17
|
+
attribute_names_from_model_klass.each do |column_name|
|
18
|
+
@columns.column(column_name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# def model_klass_reflection_keys
|
24
|
+
# @model_klass_reflection_keys ||= model_klass.reflections.keys
|
25
|
+
# end
|
26
|
+
|
27
|
+
def attribute_names_from_model_klass
|
28
|
+
model_klass.respond_to?(:column_names) ? model_klass.column_names : []
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module TableGo
|
2
|
+
class TableRenderer
|
3
|
+
attr_accessor :renderer_klass, :template
|
4
|
+
delegate :apply_options, :render_template, :to => :renderer
|
5
|
+
|
6
|
+
def initialize(source_table)
|
7
|
+
@source_table = source_table
|
8
|
+
end
|
9
|
+
|
10
|
+
def renderer
|
11
|
+
@renderer ||= renderer_klass.new.tap do |r|
|
12
|
+
r.template = template
|
13
|
+
r.source_table = @source_table
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
data/lib/table_go.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'table_go/version'
|
2
|
+
|
3
|
+
module TableGo
|
4
|
+
autoload :Table, 'table_go/table'
|
5
|
+
autoload :Columns, 'table_go/columns'
|
6
|
+
autoload :Column, 'table_go/column'
|
7
|
+
autoload :TableRenderer, 'table_go/table_renderer'
|
8
|
+
autoload :Renderers, 'table_go/renderers'
|
9
|
+
autoload :Formatter, 'table_go/formatter'
|
10
|
+
autoload :Helpers, 'table_go/helpers'
|
11
|
+
|
12
|
+
|
13
|
+
def self.render_html(collection, model_klass, template, options = {}, &block)
|
14
|
+
render(collection, model_klass, TableGo::Renderers::HtmlRenderer, template, options, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.render_csv(collection, model_klass, options = {}, &block)
|
18
|
+
render(collection, model_klass, TableGo::Renderers::CsvRenderer, nil, options, &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.render(collection, model_klass, renderer_klass, template, options = {}, &block)
|
22
|
+
table = Table.new(collection, model_klass, &block)
|
23
|
+
renderer = TableRenderer.new(table)
|
24
|
+
renderer.renderer_klass = renderer_klass
|
25
|
+
renderer.template = template
|
26
|
+
renderer.apply_options(options)
|
27
|
+
renderer.render_template
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'table_go/railtie' if defined?(Rails)
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'rails'
|
4
|
+
require 'rspec-rails'
|
5
|
+
require 'action_controller'
|
6
|
+
# require 'active_model'
|
7
|
+
require 'ostruct'
|
8
|
+
require 'table_go'
|
9
|
+
# require 'pry'
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
# some (optional) config here
|
13
|
+
end
|
14
|
+
|
15
|
+
class String
|
16
|
+
def cleanup_html
|
17
|
+
self.gsub(/\n/,'').gsub(/>\s*</, "><").strip
|
18
|
+
end
|
19
|
+
|
20
|
+
def cleanup_csv
|
21
|
+
self.strip.gsub(/\n\s*/, "\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
class Article < OpenStruct
|
27
|
+
extend ActiveModel::Naming
|
28
|
+
extend ActiveModel::Translation
|
29
|
+
|
30
|
+
def self.column_names
|
31
|
+
[:ident, :title, :date_of_order, :vat, :price, :xmas_bonus, :my_type]
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe TableGo::Renderers::CsvRenderer do
|
5
|
+
|
6
|
+
let(:articles) do
|
7
|
+
[ Article.new(:title => 'iPutz',
|
8
|
+
:date_of_order => Date.new(2012), :ident => 1, :vat => 19, :price => 5, :xmas_bonus => true,
|
9
|
+
:my_type => 'super_type'),
|
10
|
+
Article.new(:title => 'Nutzbook',
|
11
|
+
:date_of_order => Date.new(2012), :ident => 2, :vat => 19, :price => 5, :xmas_bonus => false,
|
12
|
+
:my_type => 'hardware_type') ]
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
describe 'automatic mode' do
|
17
|
+
subject { TableGo.render_csv(articles, Article, {}) }
|
18
|
+
|
19
|
+
it 'should render a simple automatic csv table' do
|
20
|
+
subject.cleanup_csv.should == %Q(
|
21
|
+
"Ident";"Title";"Date of order";"Vat";"Price";"Xmas bonus";"My type"
|
22
|
+
"1";"iPutz";"2012-01-01";"19";"5";"true";"super_type"
|
23
|
+
"2";"Nutzbook";"2012-01-01";"19";"5";"false";"hardware_type"
|
24
|
+
).cleanup_csv
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
describe 'custom mode' do
|
32
|
+
subject do
|
33
|
+
TableGo.render_csv(articles, Article,
|
34
|
+
:title => 'one Table',
|
35
|
+
:table_html => { :id => :articles },
|
36
|
+
:row_html => { :class => :row_css_class,
|
37
|
+
:id => lambda { |record| "row_#{record.ident}" }}) do |t|
|
38
|
+
|
39
|
+
t.column :ident,
|
40
|
+
:column_html => { :class => lambda { |record, column, value| value.even? ? :even : :odd } }
|
41
|
+
|
42
|
+
t.column :vat,
|
43
|
+
:label => 'as percent',
|
44
|
+
:as => :percent
|
45
|
+
|
46
|
+
t.column :price,
|
47
|
+
:label => 'as € currency',
|
48
|
+
:as => :currency
|
49
|
+
|
50
|
+
t.column :date_of_order,
|
51
|
+
:header_html => { :class => :date, :style => :xyz, :id => :date_column },
|
52
|
+
:column_html => { :class => :date,
|
53
|
+
:style => :xyz,
|
54
|
+
:id => lambda { |record, column, value| "date_#{record.ident}" }}
|
55
|
+
|
56
|
+
t.column :date_of_order,
|
57
|
+
:as => :date,
|
58
|
+
:as_options => { :format => :short }
|
59
|
+
|
60
|
+
t.column :date_of_order,
|
61
|
+
:label => 'with custom formatter',
|
62
|
+
:as => lambda { |value, record, column| value.to_s.reverse }
|
63
|
+
|
64
|
+
# t.column :date_of_order,
|
65
|
+
# :label => 'with block level custom formatter' do |value, record, column|
|
66
|
+
|
67
|
+
# "a special<br/>value"
|
68
|
+
|
69
|
+
# end
|
70
|
+
|
71
|
+
t.column :xmas_bonus,
|
72
|
+
:as => :boolean,
|
73
|
+
:label => 'as boolean'
|
74
|
+
|
75
|
+
t.column :my_type,
|
76
|
+
:send => :titleize
|
77
|
+
|
78
|
+
# t.column :trader,
|
79
|
+
# :method => :name
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should render a html table', 'with custom attributes' do
|
85
|
+
subject.cleanup_csv.should == %Q(
|
86
|
+
"Ident";"as percent";"as € currency";"Date of order";"Date of order";"with custom formatter";"as boolean";"My type"
|
87
|
+
"1";"19.000%";"$5.00";"2012-01-01";"Jan 01";"10-10-2102";"✔";"Super Type"
|
88
|
+
"2";"19.000%";"$5.00";"2012-01-01";"Jan 01";"10-10-2102";"✘";"Hardware Type"
|
89
|
+
).cleanup_csv
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe TableGo::Renderers::HtmlRenderer do
|
5
|
+
|
6
|
+
let(:articles) do
|
7
|
+
[ Article.new(:title => 'iPutz',
|
8
|
+
:date_of_order => Date.new(2012), :ident => 1, :vat => 19, :price => 5, :xmas_bonus => true,
|
9
|
+
:my_type => 'super_type'),
|
10
|
+
Article.new(:title => 'Nutzbook',
|
11
|
+
:date_of_order => Date.new(2012), :ident => 2, :vat => 19, :price => 5, :xmas_bonus => false,
|
12
|
+
:my_type => 'hardware_type') ]
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:template) do
|
16
|
+
ActionView::Base.new.tap do |view|
|
17
|
+
view.output_buffer = ActiveSupport::SafeBuffer.new rescue ''
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'automatic mode' do
|
22
|
+
|
23
|
+
subject { TableGo.render_html(articles, Article, template, {}) }
|
24
|
+
|
25
|
+
it 'should render a simple automatic html table' do
|
26
|
+
subject.cleanup_html.should == %Q(
|
27
|
+
<table>
|
28
|
+
<thead>
|
29
|
+
<tr>
|
30
|
+
<th>Ident</th>
|
31
|
+
<th>Title</th>
|
32
|
+
<th>Date of order</th>
|
33
|
+
<th>Vat</th>
|
34
|
+
<th>Price</th>
|
35
|
+
<th>Xmas bonus</th>
|
36
|
+
<th>My type</th>
|
37
|
+
</tr>
|
38
|
+
</thead>
|
39
|
+
<tbody>
|
40
|
+
<tr>
|
41
|
+
<td>1</td>
|
42
|
+
<td>iPutz</td>
|
43
|
+
<td>2012-01-01</td>
|
44
|
+
<td>19</td>
|
45
|
+
<td>5</td>
|
46
|
+
<td>true</td>
|
47
|
+
<td>super_type</td>
|
48
|
+
</tr>
|
49
|
+
<tr>
|
50
|
+
<td>2</td>
|
51
|
+
<td>Nutzbook</td>
|
52
|
+
<td>2012-01-01</td>
|
53
|
+
<td>19</td>
|
54
|
+
<td>5</td>
|
55
|
+
<td>false</td>
|
56
|
+
<td>hardware_type</td>
|
57
|
+
</tr>
|
58
|
+
</tbody>
|
59
|
+
</table>
|
60
|
+
).cleanup_html
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
describe 'custom mode' do
|
68
|
+
subject do
|
69
|
+
TableGo.render_html(articles, Article, template,
|
70
|
+
:title => 'one Table',
|
71
|
+
:table_html => { :id => :articles },
|
72
|
+
:row_html => { :class => :row_css_class,
|
73
|
+
:id => lambda { |record| "row_#{record.ident}" }}) do |t|
|
74
|
+
|
75
|
+
t.column :ident,
|
76
|
+
:column_html => { :class => lambda { |record, column, value| value.even? ? :even : :odd } }
|
77
|
+
|
78
|
+
t.column :vat,
|
79
|
+
:label => 'as percent',
|
80
|
+
:as => :percent
|
81
|
+
|
82
|
+
t.column :price,
|
83
|
+
:label => 'as € currency',
|
84
|
+
:as => :currency
|
85
|
+
|
86
|
+
t.column :date_of_order,
|
87
|
+
:header_html => { :class => :date, :style => :xyz, :id => :date_column },
|
88
|
+
:column_html => { :class => :date,
|
89
|
+
:style => :xyz,
|
90
|
+
:id => lambda { |record, column, value| "date_#{record.ident}" }}
|
91
|
+
|
92
|
+
t.column :date_of_order,
|
93
|
+
:as => :date,
|
94
|
+
:as_options => { :format => :short }
|
95
|
+
|
96
|
+
t.column :date_of_order,
|
97
|
+
:label => 'with custom formatter',
|
98
|
+
:as => lambda { |value, record, column| value.to_s.reverse }
|
99
|
+
|
100
|
+
# t.column :date_of_order,
|
101
|
+
# :label => 'with block level custom formatter' do |value, record, column|
|
102
|
+
|
103
|
+
# "a special<br/>value"
|
104
|
+
|
105
|
+
# end
|
106
|
+
|
107
|
+
t.column :xmas_bonus,
|
108
|
+
:as => :boolean,
|
109
|
+
:label => 'as boolean'
|
110
|
+
|
111
|
+
t.column :my_type,
|
112
|
+
:send => :titleize
|
113
|
+
|
114
|
+
# t.column :trader,
|
115
|
+
# :method => :name
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should render a html table', 'with custom attributes' do
|
121
|
+
subject.cleanup_html.should == %Q(
|
122
|
+
<table id="articles">
|
123
|
+
<caption>one Table</caption>
|
124
|
+
<thead>
|
125
|
+
<tr>
|
126
|
+
<th>Ident</th>
|
127
|
+
<th>as percent</th>
|
128
|
+
<th>as € currency</th>
|
129
|
+
<th class="date" id="date_column" style="xyz">Date of order</th>
|
130
|
+
<th>Date of order</th>
|
131
|
+
<th>with custom formatter</th>
|
132
|
+
<th>as boolean</th>
|
133
|
+
<th>My type</th>
|
134
|
+
</tr>
|
135
|
+
</thead>
|
136
|
+
<tbody>
|
137
|
+
<tr class="row_css_class" id="row_1">
|
138
|
+
<td class="odd">1</td>
|
139
|
+
<td>19.000%</td>
|
140
|
+
<td>$5.00</td>
|
141
|
+
<td class="date" id="date_1" style="xyz">2012-01-01</td>
|
142
|
+
<td>Jan 01</td>
|
143
|
+
<td>10-10-2102</td>
|
144
|
+
<td>✔</td>
|
145
|
+
<td>Super Type</td>
|
146
|
+
</tr>
|
147
|
+
<tr class="row_css_class" id="row_2">
|
148
|
+
<td class="even">2</td>
|
149
|
+
<td>19.000%</td>
|
150
|
+
<td>$5.00</td>
|
151
|
+
<td class="date" id="date_2" style="xyz">2012-01-01</td>
|
152
|
+
<td>Jan 01</td>
|
153
|
+
<td>10-10-2102</td>
|
154
|
+
<td>✘</td>
|
155
|
+
<td>Hardware Type</td>
|
156
|
+
</tr>
|
157
|
+
</tbody>
|
158
|
+
</table>
|
159
|
+
).cleanup_html
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
data/table_go.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'table_go/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.authors = ['Lars Gollnow', 'Vladimir Glusic']
|
8
|
+
gem.email = ['lg@megorei.com', 'exsemt@gmail.com']
|
9
|
+
gem.description = %q{simple, flexible and fast html table generator}
|
10
|
+
gem.summary = %q{}
|
11
|
+
gem.homepage = 'http://github.com/megorei/table_go/'
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($\)
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
|
+
gem.name = 'table_go'
|
17
|
+
gem.require_paths = ['lib']
|
18
|
+
gem.version = TableGo::VERSION
|
19
|
+
|
20
|
+
gem.add_dependency 'actionpack'
|
21
|
+
gem.add_dependency 'fastercsv'
|
22
|
+
|
23
|
+
gem.add_development_dependency 'rspec'
|
24
|
+
end
|
25
|
+
|
26
|
+
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: table_go
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lars Gollnow
|
8
|
+
- Vladimir Glusic
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2013-09-25 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: actionpack
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- &id002
|
21
|
+
- ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: fastercsv
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- *id002
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id003
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rspec
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- *id002
|
40
|
+
type: :development
|
41
|
+
version_requirements: *id004
|
42
|
+
description: simple, flexible and fast html table generator
|
43
|
+
email:
|
44
|
+
- lg@megorei.com
|
45
|
+
- exsemt@gmail.com
|
46
|
+
executables: []
|
47
|
+
|
48
|
+
extensions: []
|
49
|
+
|
50
|
+
extra_rdoc_files: []
|
51
|
+
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- .rspec
|
55
|
+
- Gemfile
|
56
|
+
- Gemfile.lock
|
57
|
+
- LICENSE
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- lib/table_go.rb
|
61
|
+
- lib/table_go/column.rb
|
62
|
+
- lib/table_go/columns.rb
|
63
|
+
- lib/table_go/formatter.rb
|
64
|
+
- lib/table_go/helpers.rb
|
65
|
+
- lib/table_go/railtie.rb
|
66
|
+
- lib/table_go/renderers.rb
|
67
|
+
- lib/table_go/renderers/csv_renderer.rb
|
68
|
+
- lib/table_go/renderers/html_renderer.rb
|
69
|
+
- lib/table_go/renderers/renderer_base.rb
|
70
|
+
- lib/table_go/table.rb
|
71
|
+
- lib/table_go/table_renderer.rb
|
72
|
+
- lib/table_go/version.rb
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
- spec/table_go/renderers/csv_renderer_spec.rb
|
75
|
+
- spec/table_go/renderers/html_renderer_spec.rb
|
76
|
+
- table_go.gemspec
|
77
|
+
homepage: http://github.com/megorei/table_go/
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
metadata: {}
|
81
|
+
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- *id002
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- *id002
|
93
|
+
requirements: []
|
94
|
+
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 2.1.5
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: ""
|
100
|
+
test_files:
|
101
|
+
- spec/spec_helper.rb
|
102
|
+
- spec/table_go/renderers/csv_renderer_spec.rb
|
103
|
+
- spec/table_go/renderers/html_renderer_spec.rb
|