tableview 0.1.0
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.
- 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
|
+
|