tableview 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.rvm +1 -0
- data/Gemfile +4 -0
- data/README.md +44 -0
- data/Rakefile +2 -0
- data/lib/tableview/helper.rb +21 -0
- data/lib/tableview/output/ascii.rb +20 -0
- data/lib/tableview/output/csv.rb +24 -0
- data/lib/tableview/output/html.rb +48 -0
- data/lib/tableview/output/xls.rb +46 -0
- data/lib/tableview/responder.rb +30 -0
- data/lib/tableview/tv.rb +16 -0
- data/lib/tableview/version.rb +3 -0
- data/lib/tableview/view_handler.rb +137 -0
- data/lib/tableview.rb +27 -0
- data/tableview.gemspec +26 -0
- metadata +124 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
Tableview
|
2
|
+
=========
|
3
|
+
|
4
|
+
|
5
|
+
Tableview is a gem to be used in Rails to create table like views.
|
6
|
+
|
7
|
+
Installation
|
8
|
+
============
|
9
|
+
|
10
|
+
|
11
|
+
In your Gemfile:
|
12
|
+
|
13
|
+
|
14
|
+
gem 'tablevie'
|
15
|
+
|
16
|
+
then
|
17
|
+
|
18
|
+
$ bundle install
|
19
|
+
|
20
|
+
Create a file in `/lib/application_responder.rb` with:
|
21
|
+
|
22
|
+
class ApplicationResponder < ActionController::Responder
|
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
|
31
|
+
|
32
|
+
Then create a partial named `_table.tv` in which you can use a DSL like this to define your table:
|
33
|
+
|
34
|
+
table.header_row do |row|
|
35
|
+
row.cell "First header cell", :align => :right
|
36
|
+
row.cell "You can do", "more cells at once"
|
37
|
+
end
|
38
|
+
|
39
|
+
@posts.each do |post|
|
40
|
+
table.row do |row|
|
41
|
+
row.cell post.title
|
42
|
+
row.cell post.body if format.xls?
|
43
|
+
end
|
44
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Tableview::Helper
|
2
|
+
|
3
|
+
class Format
|
4
|
+
def initialize(p)
|
5
|
+
@params = p
|
6
|
+
end
|
7
|
+
|
8
|
+
def html?
|
9
|
+
@params[:format] == :html || @params[:format].blank?
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(name, args, &blk)
|
13
|
+
if m = name.match(/^(.+)\?$/)
|
14
|
+
@params[:format] == m.captures.first
|
15
|
+
else
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Tableview::Ouput
|
2
|
+
class ASCII
|
3
|
+
require 'terminal-table/import'
|
4
|
+
def process(tv)
|
5
|
+
@table = table { |t|
|
6
|
+
tv.parts.each do |part|
|
7
|
+
part.rows.each do |row|
|
8
|
+
t.add_row row.cells.map {|cell| {:value => cell.contents}.merge(cell.options) }
|
9
|
+
end
|
10
|
+
t.add_separator unless part == tv.parts.last
|
11
|
+
end
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
@table.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Tableview::Ouput
|
2
|
+
class CSV
|
3
|
+
require 'csv'
|
4
|
+
def process(tv)
|
5
|
+
@table = ::CSV.generate("") { |csv|
|
6
|
+
tv.parts.each do |part|
|
7
|
+
part.rows.each do |row|
|
8
|
+
r = []
|
9
|
+
row.cells.each do |cell|
|
10
|
+
r << cell.contents
|
11
|
+
r += [nil] * (cell.options[:colspan] - 1) if cell.options[:colspan]
|
12
|
+
end
|
13
|
+
csv << r
|
14
|
+
end
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
@table.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Tableview::Ouput
|
2
|
+
class HTML
|
3
|
+
def process(tv)
|
4
|
+
@table = ""
|
5
|
+
@p = 0
|
6
|
+
tag :table, tv.options do
|
7
|
+
|
8
|
+
tv.parts.each do |part|
|
9
|
+
tag (case part.class.to_s
|
10
|
+
when "Tableview::ViewHandler::Header"
|
11
|
+
header = true
|
12
|
+
:thead
|
13
|
+
when "Tableview::ViewHandler::Footer"
|
14
|
+
:tfoot
|
15
|
+
when "Tableview::ViewHandler::Body"
|
16
|
+
:tbody
|
17
|
+
end), part.options do
|
18
|
+
|
19
|
+
part.rows.each do |row|
|
20
|
+
tag :tr, row.options do
|
21
|
+
row.cells.each do |cell|
|
22
|
+
tag( header || cell.options[:header] ? :th : :td, cell.options) do
|
23
|
+
@table += ERB::Util::html_escape(cell.contents.to_s)
|
24
|
+
end #td / #th
|
25
|
+
end
|
26
|
+
end #tr
|
27
|
+
end
|
28
|
+
|
29
|
+
end #t{part}
|
30
|
+
end
|
31
|
+
end #table
|
32
|
+
end
|
33
|
+
|
34
|
+
def tag(tag, attributes = {})
|
35
|
+
atrs = attributes.map {|k,v| " #{k}=\"#{v}\"" }.join
|
36
|
+
@table += "\n#{" "*@p}<#{tag}#{atrs}>"
|
37
|
+
@p += 2
|
38
|
+
yield
|
39
|
+
@p -= 2
|
40
|
+
@table += "\n#{" " * @p}</#{tag}>"
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
@table.html_safe.to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Tableview::Ouput
|
2
|
+
class XLS
|
3
|
+
require 'spreadsheet'
|
4
|
+
HEADER_STYLE = {:align => :center, :weight => :bold, :size => 12}
|
5
|
+
FOOTER_STYLE = {:weight => :bold }
|
6
|
+
|
7
|
+
def process(tv)
|
8
|
+
|
9
|
+
@table = Spreadsheet::Workbook.new
|
10
|
+
|
11
|
+
sheet1 = @table.create_worksheet
|
12
|
+
|
13
|
+
offset = 0
|
14
|
+
|
15
|
+
tv.parts.each do |part|
|
16
|
+
p_style = case part.class.to_s
|
17
|
+
when "Tableview::ViewHandler::Header"
|
18
|
+
HEADER_STYLE.dup
|
19
|
+
when "Tableview::ViewHandler::Footer"
|
20
|
+
FOOTER_STYLE.dup
|
21
|
+
else
|
22
|
+
{}
|
23
|
+
end.merge part.options
|
24
|
+
|
25
|
+
part.rows.each do |row|
|
26
|
+
style = p_style.merge row.options
|
27
|
+
row.cells.each_with_index do |cell, i|
|
28
|
+
format = Spreadsheet::Format.new style.merge(cell.options)
|
29
|
+
sheet1[offset, i] = cell.contents
|
30
|
+
sheet1.row(offset).set_format i, format
|
31
|
+
end
|
32
|
+
offset += 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
io = StringIO.new
|
40
|
+
@table.write(io)
|
41
|
+
io.rewind
|
42
|
+
string = io.read
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Tableview
|
2
|
+
module Responder
|
3
|
+
|
4
|
+
#def initialize(controller, resources, options={})
|
5
|
+
# super
|
6
|
+
#end
|
7
|
+
|
8
|
+
|
9
|
+
def to_html
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
#def to_format
|
14
|
+
# puts "#to_format with format=#{format.inspect} called"
|
15
|
+
#end
|
16
|
+
|
17
|
+
def to_csv
|
18
|
+
controller.send_data(controller.render_to_string :partial => "table")
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_xls
|
22
|
+
controller.send_data(controller.render_to_string :partial => "table")
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_ascii
|
26
|
+
render :partial => "table"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/lib/tableview/tv.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Tableview
|
2
|
+
class TV
|
3
|
+
def call(template)
|
4
|
+
%{
|
5
|
+
format = Tableview::Helper::Format.new(params)
|
6
|
+
tv = Tableview::ViewHandler.table do |table|
|
7
|
+
#{template.source}
|
8
|
+
end
|
9
|
+
output = Tableview::output_class(params[:format]).new
|
10
|
+
output.process(tv)
|
11
|
+
output.to_s
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'tableview/helper'
|
2
|
+
module Tableview
|
3
|
+
class ViewHandler
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
attr_reader :table
|
8
|
+
|
9
|
+
def self.table(opts = {}, &block)
|
10
|
+
ret = Table.new opts
|
11
|
+
#ret.instance_eval &block
|
12
|
+
yield(ret)
|
13
|
+
ret
|
14
|
+
end
|
15
|
+
|
16
|
+
class TablePiece
|
17
|
+
attr_accessor :options
|
18
|
+
def initialize(opts = {})
|
19
|
+
self.options = opts
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Table < TablePiece
|
24
|
+
attr_accessor :parts
|
25
|
+
def initialize(*args)
|
26
|
+
super *args
|
27
|
+
self.parts = []
|
28
|
+
@current_part = Body.new
|
29
|
+
@added = false
|
30
|
+
end
|
31
|
+
|
32
|
+
def config(opts)
|
33
|
+
self.options = opts
|
34
|
+
end
|
35
|
+
|
36
|
+
def part(obj, opts, &block)
|
37
|
+
prev = @current_part
|
38
|
+
added = @added
|
39
|
+
@added = true
|
40
|
+
@current_part = obj.new opts
|
41
|
+
yield @current_part
|
42
|
+
self.parts << @current_part
|
43
|
+
@current_part = prev
|
44
|
+
@added = added
|
45
|
+
end
|
46
|
+
|
47
|
+
def header(opts = {}, &block)
|
48
|
+
self.part Header, opts, &block
|
49
|
+
end
|
50
|
+
|
51
|
+
def header_row(opts = {}, &block)
|
52
|
+
self.header do |table|
|
53
|
+
table.row opts, &block
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def footer(opts = {}, &block)
|
58
|
+
self.part Footer, opts, &block
|
59
|
+
end
|
60
|
+
|
61
|
+
def footer_row(opts = {}, &block)
|
62
|
+
self.footer do |t|
|
63
|
+
t.row opts, &block
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def body(opts = {}, &block)
|
68
|
+
self.part Body, opts, &block
|
69
|
+
end
|
70
|
+
|
71
|
+
def row(opts = {}, &block)
|
72
|
+
unless @added
|
73
|
+
@parts << @current_part
|
74
|
+
@added = true
|
75
|
+
end
|
76
|
+
@current_part.send :row, opts, &block
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class Part < TablePiece
|
81
|
+
attr_accessor :rows
|
82
|
+
def initialize(*args)
|
83
|
+
super *args
|
84
|
+
self.rows = []
|
85
|
+
end
|
86
|
+
|
87
|
+
def row(opts = {}, &block)
|
88
|
+
row = Row.new opts
|
89
|
+
yield row
|
90
|
+
self.rows << row
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Header < Part
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
class Body < Part
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
class Footer < Part
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
class Row < TablePiece
|
107
|
+
attr_accessor :cells
|
108
|
+
def initialize(*args)
|
109
|
+
super *args
|
110
|
+
self.cells = []
|
111
|
+
end
|
112
|
+
|
113
|
+
def cell(*contents)
|
114
|
+
opts = contents.extract_options!.symbolize_keys
|
115
|
+
contents.each do |c|
|
116
|
+
self.cells << Cell.new(c, opts)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
#alias_method :cells, :cell
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
class Cell < TablePiece
|
125
|
+
attr_accessor :contents
|
126
|
+
def initialize(contents, opts)
|
127
|
+
self.contents = contents
|
128
|
+
super opts
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
|
data/lib/tableview.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'action_dispatch/http/mime_type'
|
2
|
+
Mime::Type.register "application/vnd.ms-excel", :xls
|
3
|
+
Mime::Type.register "text/plain", :ascii
|
4
|
+
|
5
|
+
|
6
|
+
require 'tableview/tv'
|
7
|
+
require 'tableview/view_handler'
|
8
|
+
require 'tableview/responder'
|
9
|
+
|
10
|
+
|
11
|
+
ActionView::Template.register_template_handler 'tv', Tableview::TV.new
|
12
|
+
|
13
|
+
module Tableview
|
14
|
+
def self.output_class(format)
|
15
|
+
format = :html if format.blank?
|
16
|
+
begin
|
17
|
+
require File.join(File.dirname(__FILE__), "tableview", "output", format.to_s.downcase)
|
18
|
+
rescue
|
19
|
+
raise NoOuputClassError
|
20
|
+
end
|
21
|
+
("Tableview::Ouput::" + format.to_s.upcase).constantize
|
22
|
+
end
|
23
|
+
|
24
|
+
class NoOuputClassError
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
data/tableview.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/tableview/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "tableview"
|
6
|
+
s.version = Tableview::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Jakub Hampl"]
|
9
|
+
s.email = ["honitom@seznam.cz"]
|
10
|
+
s.homepage = "http://rubygems.org/gems/tableview"
|
11
|
+
s.summary = "Tableview is a DSL for specifying tables in Rails views that can output in multiple formats"
|
12
|
+
s.description = "Supported formats are ASCII, MS Excel, HTML and CSV; it is easy to create your own exporter class."
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "tableview"
|
16
|
+
|
17
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
18
|
+
|
19
|
+
s.add_dependency "terminal-table", "~> 1.4"
|
20
|
+
s.add_dependency "spreadsheet", "~> 0.6"
|
21
|
+
#s.add_dependency "rails", "~> 3.0"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
25
|
+
s.require_path = 'lib'
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tableview
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Jakub Hampl
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-02-28 00:00:00 +00:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: bundler
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
version: 1.0.0
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: terminal-table
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 1
|
45
|
+
- 4
|
46
|
+
version: "1.4"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: spreadsheet
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
- 6
|
60
|
+
version: "0.6"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
description: Supported formats are ASCII, MS Excel, HTML and CSV; it is easy to create your own exporter class.
|
64
|
+
email:
|
65
|
+
- honitom@seznam.cz
|
66
|
+
executables: []
|
67
|
+
|
68
|
+
extensions: []
|
69
|
+
|
70
|
+
extra_rdoc_files: []
|
71
|
+
|
72
|
+
files:
|
73
|
+
- .gitignore
|
74
|
+
- .rvm
|
75
|
+
- Gemfile
|
76
|
+
- README.md
|
77
|
+
- Rakefile
|
78
|
+
- lib/tableview.rb
|
79
|
+
- lib/tableview/helper.rb
|
80
|
+
- lib/tableview/output/ascii.rb
|
81
|
+
- lib/tableview/output/csv.rb
|
82
|
+
- lib/tableview/output/html.rb
|
83
|
+
- lib/tableview/output/xls.rb
|
84
|
+
- lib/tableview/responder.rb
|
85
|
+
- lib/tableview/tv.rb
|
86
|
+
- lib/tableview/version.rb
|
87
|
+
- lib/tableview/view_handler.rb
|
88
|
+
- tableview.gemspec
|
89
|
+
has_rdoc: true
|
90
|
+
homepage: http://rubygems.org/gems/tableview
|
91
|
+
licenses: []
|
92
|
+
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
segments:
|
112
|
+
- 1
|
113
|
+
- 3
|
114
|
+
- 6
|
115
|
+
version: 1.3.6
|
116
|
+
requirements: []
|
117
|
+
|
118
|
+
rubyforge_project: tableview
|
119
|
+
rubygems_version: 1.3.7
|
120
|
+
signing_key:
|
121
|
+
specification_version: 3
|
122
|
+
summary: Tableview is a DSL for specifying tables in Rails views that can output in multiple formats
|
123
|
+
test_files: []
|
124
|
+
|