poormans_export 0.1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +64 -0
- data/Rakefile +29 -0
- data/lib/poormans_export.rb +6 -0
- data/lib/poormans_export/exporter.rb +186 -0
- data/lib/poormans_export/version.rb +5 -0
- data/lib/tasks/poormans_export_tasks.rake +5 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0512d8f5b14c154addca9d079e50f10ed70ff42be9f298d16be0e43303fb9513
|
4
|
+
data.tar.gz: ba9db716689c2666e67d44720f27f76d46335db2bcb090f3bc9e7bc0722aef86
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9c82d6e3676b9b1e01c9d678bbc98a088f107f1859ea433b2c3f1ac5fb029ae52baac922ee5bf8f6f99adfbb3f9397404d2a187064c97c4059e5a634091ce0b0
|
7
|
+
data.tar.gz: eebb11a1e9a02174092893a57db84a717fd30691c37ffda89ab0c6b209dc551d8cdfe8e9168a052a4af71312c653a906f044edeb4259edbe7451ebf404f4087f
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2019 Usabi
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# Poorman's Export
|
2
|
+
Poorman's Export is a simple but powerful CSV and XLS exporter.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
Poorman's Export transforms a collection of objects into a CSV or a XLS file that can be sent to the browser just like this:
|
6
|
+
```ruby
|
7
|
+
def index
|
8
|
+
@collection = Article.all
|
9
|
+
fields_to_export = %i[id title body created_at published_at]
|
10
|
+
|
11
|
+
respond_to do |format|
|
12
|
+
format.html
|
13
|
+
format.csv do
|
14
|
+
send_data(
|
15
|
+
PoormansExport::Exporter.new(@collection, fields_to_export).csv_string,
|
16
|
+
type: 'text/csv; charset=utf-16le; header=present',
|
17
|
+
disposition: 'attachment',
|
18
|
+
filename: 'articles.csv'
|
19
|
+
)
|
20
|
+
end
|
21
|
+
format.xls do
|
22
|
+
send_data(
|
23
|
+
PoormansExport::Exporter.new(@collection, fields_to_export).xls_string,
|
24
|
+
type: 'application/xls',
|
25
|
+
disposition: 'attachment',
|
26
|
+
filename: 'articles.xls'
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
Poorman's Export will process the collection and convert its fields into something readable by a human, automatically processing dates, times, booleans and even relations, by using the `to_s` method of the related object.
|
34
|
+
|
35
|
+
## Installation
|
36
|
+
Add this line to your application's Gemfile:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
gem 'poormans_export'
|
40
|
+
```
|
41
|
+
|
42
|
+
And then execute:
|
43
|
+
```bash
|
44
|
+
$ bundle
|
45
|
+
```
|
46
|
+
|
47
|
+
Or install it yourself as:
|
48
|
+
```bash
|
49
|
+
$ gem install poormans_export
|
50
|
+
```
|
51
|
+
|
52
|
+
After installing the gem, register the CSV and XLS MIME types in your application by adding these lines to your `config/initializers/mime_types.rb` file:
|
53
|
+
```ruby
|
54
|
+
Mime::Type.register 'text/csv; charset=utf-16le; header=present', :csv
|
55
|
+
Mime::Type.register 'application/xls', :xls
|
56
|
+
```
|
57
|
+
|
58
|
+
And you're good to go!
|
59
|
+
|
60
|
+
## Contributing
|
61
|
+
Contribution directions go here.
|
62
|
+
|
63
|
+
## License
|
64
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'rdoc/task'
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = 'PoormansExport'
|
14
|
+
rdoc.options << '--line-numbers'
|
15
|
+
rdoc.rdoc_files.include('README.md')
|
16
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'bundler/gem_tasks'
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
|
23
|
+
Rake::TestTask.new(:test) do |t|
|
24
|
+
t.libs << 'test'
|
25
|
+
t.pattern = 'test/**/*_test.rb'
|
26
|
+
t.verbose = false
|
27
|
+
end
|
28
|
+
|
29
|
+
task default: :test
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
require 'spreadsheet'
|
5
|
+
|
6
|
+
module PoormansExport
|
7
|
+
class Exporter
|
8
|
+
def initialize(collection, fields, headers = [])
|
9
|
+
@collection = collection
|
10
|
+
@head = []
|
11
|
+
@fields = []
|
12
|
+
@types = []
|
13
|
+
fields.each do |f|
|
14
|
+
if f.is_a?(Symbol) || f.is_a?(String)
|
15
|
+
@head << f.to_s
|
16
|
+
@fields << f
|
17
|
+
elsif f.is_a?(Hash)
|
18
|
+
@head << f.keys.first
|
19
|
+
@fields << f.values.first
|
20
|
+
@types << f[:type]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
@headers = headers
|
24
|
+
end
|
25
|
+
|
26
|
+
def csv_string(params = {})
|
27
|
+
options = { col_sep: ',' }
|
28
|
+
options.merge! params
|
29
|
+
csv_string = CSV.generate(options) do |csv|
|
30
|
+
if @collection.first.class.nil?
|
31
|
+
class_name = @collection
|
32
|
+
elsif @collection.first.class != NilClass
|
33
|
+
class_name = @collection.first.class
|
34
|
+
end
|
35
|
+
|
36
|
+
header = []
|
37
|
+
@head.each do |header_field|
|
38
|
+
header <<
|
39
|
+
if class_name
|
40
|
+
class_name.human_attribute_name(header_field.gsub(/_ids?/, ''))
|
41
|
+
else
|
42
|
+
header_field
|
43
|
+
end
|
44
|
+
end
|
45
|
+
csv << header
|
46
|
+
|
47
|
+
@collection.each do |item|
|
48
|
+
row_array = []
|
49
|
+
@fields.each do |field|
|
50
|
+
row_array << Exporter.field_value(item, field)
|
51
|
+
end
|
52
|
+
csv << row_array
|
53
|
+
end
|
54
|
+
end
|
55
|
+
csv_string
|
56
|
+
end
|
57
|
+
|
58
|
+
def xls_string(params = {})
|
59
|
+
template_path = params[:template]
|
60
|
+
start_on_row = params[:start_on_row] || 0
|
61
|
+
formats = params[:formats] || { 0 => { weight: :bold } }
|
62
|
+
formats[@headers.size + 1] = { weight: :bold } unless @headers.empty?
|
63
|
+
workbook = params[:workbook]
|
64
|
+
workbook ||=
|
65
|
+
if template_path.present?
|
66
|
+
::Spreadsheet.open(template_path)
|
67
|
+
else
|
68
|
+
::Spreadsheet::Workbook.new
|
69
|
+
end
|
70
|
+
sheet = template_path ? workbook.worksheet(0) : workbook.create_worksheet
|
71
|
+
sheet.name = params[:sheet_name] if params[:sheet_name]
|
72
|
+
current_row = start_on_row
|
73
|
+
|
74
|
+
if @collection.first.class.nil?
|
75
|
+
class_name = @collection
|
76
|
+
elsif @collection.first.class != NilClass
|
77
|
+
class_name = @collection.first.class
|
78
|
+
end
|
79
|
+
|
80
|
+
unless @headers.empty?
|
81
|
+
if @headers[0]
|
82
|
+
sheet.row(current_row).concat [@headers[0]]
|
83
|
+
current_row += 1
|
84
|
+
end
|
85
|
+
sheet.row(current_row).concat [I18n.l(Time.zone.now, format: :compact)]
|
86
|
+
current_row += 1
|
87
|
+
if @headers[1]
|
88
|
+
sheet.row(current_row).concat [@headers[1]]
|
89
|
+
current_row += 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
header = []
|
94
|
+
@head.each do |header_field|
|
95
|
+
header <<
|
96
|
+
if class_name
|
97
|
+
class_name.human_attribute_name(header_field.gsub(/_ids?/, ''))
|
98
|
+
else
|
99
|
+
header_field
|
100
|
+
end
|
101
|
+
end
|
102
|
+
sheet.row(current_row).concat header
|
103
|
+
current_row += 1
|
104
|
+
|
105
|
+
@collection.each do |item|
|
106
|
+
row_array = []
|
107
|
+
@fields.each do |field|
|
108
|
+
row_array << Exporter.field_value(item, field)
|
109
|
+
end
|
110
|
+
sheet.row(current_row).replace row_array
|
111
|
+
@types.each_with_index do |type, idx|
|
112
|
+
case type
|
113
|
+
when Date
|
114
|
+
cell_format = 'DD-MM-YYYY'
|
115
|
+
when Time
|
116
|
+
cell_format = 'DD-MM-YYYY HH:MM:SS'
|
117
|
+
end
|
118
|
+
next unless cell_format
|
119
|
+
|
120
|
+
sheet.row(current_row).set_format(
|
121
|
+
idx,
|
122
|
+
Spreadsheet::Format.new(number_format: cell_format)
|
123
|
+
)
|
124
|
+
end
|
125
|
+
current_row += 1
|
126
|
+
end
|
127
|
+
|
128
|
+
formats.each do |k, v|
|
129
|
+
format = Spreadsheet::Format.new(v)
|
130
|
+
if k.respond_to?(:each)
|
131
|
+
k.each do |sub_k|
|
132
|
+
sheet.row(sub_k).default_format = format
|
133
|
+
end
|
134
|
+
else
|
135
|
+
sheet.row(k).default_format = format
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if params[:format] == :object
|
140
|
+
workbook
|
141
|
+
else
|
142
|
+
output = StringIO.new
|
143
|
+
workbook.write(output)
|
144
|
+
output.string
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.field_value(item, field)
|
149
|
+
if item && field.is_a?(Proc)
|
150
|
+
Exporter.format field.call(item)
|
151
|
+
elsif field =~ /(.+)_id$/
|
152
|
+
Exporter.format item.send(Regexp.last_match(1))
|
153
|
+
elsif field =~ /(.+)_ids$/
|
154
|
+
item.send(Regexp.last_match(1)).map do |f|
|
155
|
+
Exporter.format f
|
156
|
+
end.join('; ')
|
157
|
+
elsif field.in? %w[status state]
|
158
|
+
I18n.t(item.send(field), scope: field.to_sym)
|
159
|
+
elsif item.is_a?(Hash)
|
160
|
+
Exporter.format item[field]
|
161
|
+
else
|
162
|
+
Exporter.format item.send(field)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.format(val)
|
167
|
+
val = Time.zone.parse(val) if val.is_a?(String) && val =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/
|
168
|
+
|
169
|
+
if val.is_a?(ActiveRecord::Base)
|
170
|
+
val.try(:to_s)
|
171
|
+
elsif val.is_a? Time
|
172
|
+
I18n.l(val, format: :compact)
|
173
|
+
elsif val.is_a? Date
|
174
|
+
I18n.l(val, format: :default)
|
175
|
+
elsif val.is_a? BigDecimal
|
176
|
+
val.to_f
|
177
|
+
elsif val.is_a?(FalseClass) || val.is_a?(TrueClass)
|
178
|
+
I18n.t(val ? 'yes' : 'no')
|
179
|
+
elsif val.nil?
|
180
|
+
'-'
|
181
|
+
else
|
182
|
+
val
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: poormans_export
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Imobach González Sosa
|
8
|
+
- Ignacio Aliende García
|
9
|
+
- Adán Alonso Salvador
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2020-07-29 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rails
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 4.2.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: 4.2.0
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: spreadsheet
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - "~>"
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '1.0'
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '1.0'
|
43
|
+
description: Poorman's Export is a simple but powerful CSV and XLS exporter
|
44
|
+
email:
|
45
|
+
- imobachgs@banot.net
|
46
|
+
- ialiendeg@gmail.com
|
47
|
+
- adan.alonso.s@gmail.com
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- MIT-LICENSE
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- lib/poormans_export.rb
|
56
|
+
- lib/poormans_export/exporter.rb
|
57
|
+
- lib/poormans_export/version.rb
|
58
|
+
- lib/tasks/poormans_export_tasks.rake
|
59
|
+
homepage: https://github.com/Usabi/poormans_export
|
60
|
+
licenses:
|
61
|
+
- MIT
|
62
|
+
metadata: {}
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubygems_version: 3.1.2
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: A simple but powerful exporter
|
82
|
+
test_files: []
|