tableview 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +26 -32
- data/lib/generators/tableview/install/install_generator.rb +16 -0
- data/lib/generators/tableview/tableview_generator.rb +23 -0
- data/lib/tableview/helper.rb +3 -2
- data/lib/tableview/output/ascii.rb +13 -9
- data/lib/tableview/output/csv.rb +1 -1
- data/lib/tableview/output/html.rb +27 -24
- data/lib/tableview/output/xls.rb +22 -24
- data/lib/tableview/tv.rb +8 -2
- data/lib/tableview/version.rb +1 -1
- data/lib/tableview/view_handler.rb +25 -6
- data/lib/tableview.rb +1 -1
- data/tableview.gemspec +2 -0
- metadata +19 -3
data/README.md
CHANGED
@@ -16,42 +16,36 @@ In your Gemfile:
|
|
16
16
|
then
|
17
17
|
|
18
18
|
$ bundle install
|
19
|
+
$ rails g tableview:install
|
19
20
|
|
20
|
-
|
21
|
+
To apply to a resource use the built in generator:
|
21
22
|
|
22
|
-
|
23
|
-
include Tableview::Responder
|
24
|
-
end
|
25
|
-
|
26
|
-
Then add this to your controller:
|
27
|
-
|
28
|
-
require "#{Rails.root}/lib/application_responder"
|
29
|
-
self.responder = ApplicationResponder
|
30
|
-
respond_to :html, :csv, :xls, :ascii, :only => :index
|
23
|
+
$ rails g tableview resource_name
|
31
24
|
|
32
|
-
|
25
|
+
This will create a partial named `_table.tv` in which you can use a DSL like this to define your table:
|
33
26
|
|
34
|
-
|
35
|
-
row.cell "First header cell", :align => :right
|
36
|
-
row.cell "You can do", "more cells at once"
|
37
|
-
end
|
27
|
+
=> @registrations
|
38
28
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
44
|
-
end
|
29
|
+
+ :first_name
|
30
|
+
+ :surname
|
31
|
+
+ :address {|reg| reg.address + "\n" + reg.postcode }
|
32
|
+
+ :friends if format.html?
|
45
33
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
We now have a column based DSL.
|
51
|
-
|
52
|
-
table.table_for @events
|
34
|
+
if format.xls?
|
35
|
+
= @registrations.some_scope, "Workbook title"
|
36
|
+
= @registration.other_scope, "Works as title in other formats as well"
|
37
|
+
end
|
53
38
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
39
|
+
The DSL is a simple superset of ruby with a few special characters (only work if first printable character on line, won't work with eval and friends).
|
40
|
+
|
41
|
+
Character | Meaning
|
42
|
+
----------|--------
|
43
|
+
`=>` | Use the passed collection for rendering and I18n
|
44
|
+
`*` | Pass a hash to this, is used to configure the formatters.
|
45
|
+
`+` | Defines a column. If passed a symbol, Tableview will use I18n to lookup the header and call the method on the model to get the value. Strings will be used literally. Optionally use a block to generate values.
|
46
|
+
`=` | Render a subtable for the passed collection. Not all formatters support subtables, use at own risk (notably the CSV formatter has no support for this). Is meant mainly to have nice full-featured excel files.
|
47
|
+
|
48
|
+
It will also add a few lines of code to your controller:
|
49
|
+
|
50
|
+
- `self.responder = ApplicationResponder` this sets up the correct code path to use for dynamically rendering all the formats.
|
51
|
+
- `respond_to :html, :json, :csv, :xls, :ascii` a list of supported formats. You will want to use `respond_with` as well.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
module Tableview
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < ::Rails::Generators::Base
|
6
|
+
desc "Creates the responder file necessary for proper working of the plugin."
|
7
|
+
def create_application_responder
|
8
|
+
# record do |m|
|
9
|
+
# m.file "definition.txt", "definition.txt"
|
10
|
+
# end
|
11
|
+
lib 'application_responder.rb', "class ApplicationResponder < ActionController::Responder\n\tinclude Tableview::Responder\nend"
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
module Tableview
|
4
|
+
module Generators
|
5
|
+
class TableviewGenerator < ::Rails::Generators::NamedBase
|
6
|
+
namespace "tableview"
|
7
|
+
desc "Generates a partial and some controller code to use tableview."
|
8
|
+
def create_partial
|
9
|
+
cols = file_name.camelize.constantize.column_names
|
10
|
+
template = "=> @#{file_name.tableize}\n\n"
|
11
|
+
cols.each do |col|
|
12
|
+
template << "+ :#{col}\n"
|
13
|
+
end
|
14
|
+
create_file "app/views/#{file_name.tableize}/_table.tv", template
|
15
|
+
end
|
16
|
+
|
17
|
+
def install_into_controller
|
18
|
+
inject_into_class "app/controllers/#{file_name.tableize}_controller.rb", file_name.camelize.pluralize + "Controller", " self.responder = ApplicationResponder\n respond_to :html, :json, :csv, :xls, :ascii"
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/tableview/helper.rb
CHANGED
@@ -9,8 +9,9 @@ module Tableview::Helper
|
|
9
9
|
@params[:format] == :html || @params[:format].blank?
|
10
10
|
end
|
11
11
|
|
12
|
-
def method_missing(name, args, &blk)
|
13
|
-
if m = name.match(/^(.+)\?$/)
|
12
|
+
def method_missing(name, *args, &blk)
|
13
|
+
if m = name.to_s.match(/^(.+)\?$/)
|
14
|
+
puts m.inspect, name.inspect
|
14
15
|
@params[:format] == m.captures.first
|
15
16
|
else
|
16
17
|
super
|
@@ -1,19 +1,23 @@
|
|
1
|
-
module Tableview::
|
1
|
+
module Tableview::Output
|
2
2
|
class ASCII
|
3
3
|
require 'terminal-table/import'
|
4
4
|
def process(tv)
|
5
|
-
@table =
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
@table = ""
|
6
|
+
tv.subtables.each do |sub|
|
7
|
+
@table << "# #{sub.title}" unless sub.title.blank?
|
8
|
+
@table << table { |t|
|
9
|
+
sub.parts.each do |part|
|
10
|
+
part.rows.each do |row|
|
11
|
+
t.add_row row.cells.map {|cell| {:value => cell.contents}.merge(cell.options) }
|
12
|
+
end
|
13
|
+
t.add_separator unless part == sub.parts.last
|
9
14
|
end
|
10
|
-
|
11
|
-
|
12
|
-
}
|
15
|
+
}.to_s
|
16
|
+
end
|
13
17
|
end
|
14
18
|
|
15
19
|
def to_s
|
16
|
-
@table
|
20
|
+
@table
|
17
21
|
end
|
18
22
|
|
19
23
|
end
|
data/lib/tableview/output/csv.rb
CHANGED
@@ -1,34 +1,37 @@
|
|
1
|
-
module Tableview::
|
1
|
+
module Tableview::Output
|
2
2
|
class HTML
|
3
3
|
def process(tv)
|
4
4
|
@table = ""
|
5
5
|
@p = 0
|
6
|
-
|
6
|
+
tv.subtables.each do |sub|
|
7
|
+
tag :h2, sub.title unless sub.title.blank?
|
8
|
+
tag :table, sub.options do
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
sub.parts.each do |part|
|
11
|
+
tag (case part.class.to_s
|
12
|
+
when "Tableview::ViewHandler::Header"
|
13
|
+
header = true
|
14
|
+
:thead
|
15
|
+
when "Tableview::ViewHandler::Footer"
|
16
|
+
:tfoot
|
17
|
+
when "Tableview::ViewHandler::Body"
|
18
|
+
:tbody
|
19
|
+
end), part.options do
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
part.rows.each do |row|
|
22
|
+
tag :tr, row.options do
|
23
|
+
row.cells.each do |cell|
|
24
|
+
tag( header || cell.options[:header] ? :th : :td, cell.options) do
|
25
|
+
@table += ERB::Util::html_escape(cell.contents.to_s)
|
26
|
+
end #td / #th
|
27
|
+
end
|
28
|
+
end #tr
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
end #t{part}
|
32
|
+
end
|
33
|
+
end #table
|
34
|
+
end
|
32
35
|
end
|
33
36
|
|
34
37
|
def tag(tag, attributes = {})
|
data/lib/tableview/output/xls.rb
CHANGED
@@ -1,38 +1,36 @@
|
|
1
|
-
module Tableview::
|
1
|
+
module Tableview::Output
|
2
2
|
class XLS
|
3
3
|
require 'spreadsheet'
|
4
|
-
HEADER_STYLE = {:align => :center, :weight => :bold
|
4
|
+
HEADER_STYLE = {:align => :center, :weight => :bold}
|
5
5
|
FOOTER_STYLE = {:weight => :bold }
|
6
6
|
|
7
7
|
def process(tv)
|
8
8
|
|
9
9
|
@table = Spreadsheet::Workbook.new
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
{}
|
23
|
-
end.merge part.options
|
10
|
+
tv.subtables.each do |sub|
|
11
|
+
sheet1 = @table.create_worksheet :name => sub.title
|
12
|
+
offset = 0
|
13
|
+
sub.parts.each do |part|
|
14
|
+
p_style = case part.class.to_s
|
15
|
+
when "Tableview::ViewHandler::Header"
|
16
|
+
HEADER_STYLE.dup
|
17
|
+
when "Tableview::ViewHandler::Footer"
|
18
|
+
FOOTER_STYLE.dup
|
19
|
+
else
|
20
|
+
{}
|
21
|
+
end.merge part.options
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
23
|
+
part.rows.each do |row|
|
24
|
+
style = p_style.merge row.options
|
25
|
+
row.cells.each_with_index do |cell, i|
|
26
|
+
format = Spreadsheet::Format.new style.merge(cell.options)
|
27
|
+
sheet1[offset, i] = cell.contents
|
28
|
+
sheet1.row(offset).set_format i, format
|
29
|
+
end
|
30
|
+
offset += 1
|
31
31
|
end
|
32
|
-
offset += 1
|
33
32
|
end
|
34
33
|
end
|
35
|
-
|
36
34
|
end
|
37
35
|
|
38
36
|
def to_s
|
data/lib/tableview/tv.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
module Tableview
|
2
2
|
class TV
|
3
3
|
def call(template)
|
4
|
+
source = template.source
|
5
|
+
start, ending = /^\s*/, /\s+(.+?)(?= unless| if| do|\{|#|$)/
|
6
|
+
source.gsub!(/#{start}\+#{ending}/, 'table.column(\1)')
|
7
|
+
source.gsub!(/#{start}\=>#{ending}/, 'table.table_for(\1)')
|
8
|
+
source.gsub!(/#{start}\=#{ending}/, 'table.generate_subtable_for(\1)')
|
9
|
+
source.gsub!(/#{start}\*#{ending}/, 'table.config(\1)')
|
4
10
|
%{
|
5
11
|
format = Tableview::Helper::Format.new(params)
|
6
|
-
tv = Tableview::ViewHandler.
|
7
|
-
#{
|
12
|
+
tv = Tableview::ViewHandler.dsl do |table|
|
13
|
+
#{source}
|
8
14
|
end
|
9
15
|
output = Tableview::output_class(params[:format]).new
|
10
16
|
output.process(tv)
|
data/lib/tableview/version.rb
CHANGED
@@ -6,7 +6,8 @@ module Tableview
|
|
6
6
|
|
7
7
|
attr_reader :table
|
8
8
|
|
9
|
-
def self.
|
9
|
+
def self.dsl(opts = {}, &block)
|
10
|
+
puts "self.dsl called"
|
10
11
|
ret = Table.new opts
|
11
12
|
#ret.instance_eval &block
|
12
13
|
yield(ret)
|
@@ -22,13 +23,13 @@ module Tableview
|
|
22
23
|
end
|
23
24
|
|
24
25
|
class Table < TablePiece
|
25
|
-
attr_accessor :parts
|
26
|
+
attr_accessor :parts, :subtables, :title
|
26
27
|
def initialize(*args)
|
27
28
|
super *args
|
28
29
|
self.parts = []
|
29
30
|
@current_part = Body.new
|
30
31
|
@added = false
|
31
|
-
@headers, @procs = [], []
|
32
|
+
@headers, @procs, @subtables = [], [], []
|
32
33
|
end
|
33
34
|
|
34
35
|
def table_for(s)
|
@@ -104,8 +105,28 @@ module Tableview
|
|
104
105
|
end
|
105
106
|
end
|
106
107
|
|
108
|
+
def generate_subtable_for(subcollection, title = nil)
|
109
|
+
t = Table.new
|
110
|
+
t.title = title
|
111
|
+
t.header_row do |row|
|
112
|
+
row.cells = @headers
|
113
|
+
end
|
114
|
+
t.body do |b|
|
115
|
+
subcollection.each do |el|
|
116
|
+
b.row do |r|
|
117
|
+
@procs.each do |proc|
|
118
|
+
r.cell proc.call(el)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end # body
|
123
|
+
@subtables << t
|
124
|
+
@table_generated = true
|
125
|
+
end
|
126
|
+
|
107
127
|
def create_table!
|
108
128
|
return unless @column_based
|
129
|
+
return if @table_generated
|
109
130
|
header_row do |row|
|
110
131
|
row.cells = @headers
|
111
132
|
end
|
@@ -116,6 +137,7 @@ module Tableview
|
|
116
137
|
end
|
117
138
|
end
|
118
139
|
end
|
140
|
+
@subtables << self
|
119
141
|
end
|
120
142
|
|
121
143
|
end
|
@@ -135,15 +157,12 @@ module Tableview
|
|
135
157
|
end
|
136
158
|
|
137
159
|
class Header < Part
|
138
|
-
|
139
160
|
end
|
140
161
|
|
141
162
|
class Body < Part
|
142
|
-
|
143
163
|
end
|
144
164
|
|
145
165
|
class Footer < Part
|
146
|
-
|
147
166
|
end
|
148
167
|
|
149
168
|
class Row < TablePiece
|
data/lib/tableview.rb
CHANGED
data/tableview.gemspec
CHANGED
@@ -18,6 +18,8 @@ Gem::Specification.new do |s|
|
|
18
18
|
|
19
19
|
s.add_dependency "terminal-table", "~> 1.4"
|
20
20
|
s.add_dependency "spreadsheet", "~> 0.6"
|
21
|
+
s.add_dependency "railties", "~> 3.0"
|
22
|
+
#s.add_dependency "thor", "~> 0.14"
|
21
23
|
#s.add_dependency "rails", "~> 3.0"
|
22
24
|
|
23
25
|
s.files = `git ls-files`.split("\n")
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 3
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jakub Hampl
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-06-01 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -60,6 +60,20 @@ dependencies:
|
|
60
60
|
version: "0.6"
|
61
61
|
type: :runtime
|
62
62
|
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: railties
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ~>
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
segments:
|
72
|
+
- 3
|
73
|
+
- 0
|
74
|
+
version: "3.0"
|
75
|
+
type: :runtime
|
76
|
+
version_requirements: *id004
|
63
77
|
description: Supported formats are ASCII, MS Excel, HTML and CSV; it is easy to create your own exporter class.
|
64
78
|
email:
|
65
79
|
- honitom@seznam.cz
|
@@ -75,6 +89,8 @@ files:
|
|
75
89
|
- Gemfile
|
76
90
|
- README.md
|
77
91
|
- Rakefile
|
92
|
+
- lib/generators/tableview/install/install_generator.rb
|
93
|
+
- lib/generators/tableview/tableview_generator.rb
|
78
94
|
- lib/tableview.rb
|
79
95
|
- lib/tableview/helper.rb
|
80
96
|
- lib/tableview/output/ascii.rb
|