to-csv 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +21 -15
- data/MIT-LICENSE +20 -20
- data/README.rdoc +237 -212
- data/Rakefile +52 -52
- data/lib/to_csv.rb +64 -63
- data/lib/to_csv/csv_converter.rb +237 -174
- data/test/database.yml +6 -4
- data/test/fixtures/block_buster.rb +3 -0
- data/test/fixtures/block_busters.yml +3 -0
- data/test/fixtures/movie.rb +8 -7
- data/test/fixtures/movies.yml +21 -19
- data/test/fixtures/people.yml +8 -7
- data/test/fixtures/person.rb +5 -3
- data/test/fixtures/schema.rb +17 -12
- data/test/lib/activerecord_test_case.rb +21 -20
- data/test/lib/activerecord_test_connector.rb +34 -32
- data/test/lib/load_fixtures.rb +10 -9
- data/test/locales/en-US.yml +27 -27
- data/test/locales/pt-BR.yml +147 -147
- data/test/tasks.rake +7 -7
- data/test/to_csv_test.rb +186 -163
- metadata +62 -28
data/CHANGELOG.rdoc
CHANGED
@@ -1,15 +1,21 @@
|
|
1
|
-
== 1.0.
|
2
|
-
|
3
|
-
*
|
4
|
-
*
|
5
|
-
*
|
6
|
-
|
7
|
-
== 1.0.
|
8
|
-
|
9
|
-
* Now
|
10
|
-
*
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
1
|
+
== 1.0.3 2010-08-09
|
2
|
+
* Supported (tested) Ruby versions: 1.8.7-p299, 1.9.1-p378, 1.9.2-rc1
|
3
|
+
* Support for Ruby 1.8.6 has been dropped
|
4
|
+
* New +include+ option
|
5
|
+
* +csv_options+ has an +encoding+ option set with UTF-8
|
6
|
+
|
7
|
+
== 1.0.2 2010-01-04
|
8
|
+
|
9
|
+
* Changed use of OpenStruct in favor of Struct, which supports any attribute name. Now a block yields a Struct and the object itself
|
10
|
+
* Support for Rails scopes
|
11
|
+
* Improved documentation
|
12
|
+
|
13
|
+
== 1.0.1 2009-12-24
|
14
|
+
|
15
|
+
* Now compatible with Ruby 1.9.1
|
16
|
+
* Updated documentation to reflect Ruby 1.9.1 support
|
17
|
+
|
18
|
+
== 1.0.0 2009-12-23
|
19
|
+
|
20
|
+
* First release
|
21
|
+
|
data/MIT-LICENSE
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
Copyright (c) 2009 Ícaro Leopoldino da Motta
|
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.
|
1
|
+
Copyright (c) 2009 Ícaro Leopoldino da Motta
|
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.rdoc
CHANGED
@@ -1,212 +1,237 @@
|
|
1
|
-
= ToCSV
|
2
|
-
|
3
|
-
|
4
|
-
ToCSV is a gem for converting arrays or scopes (Rails) to CSV by calling +to_csv+.
|
5
|
-
These arrays can contain different data structures, as long as they are homogeneous, like the ones
|
6
|
-
described below:
|
7
|
-
|
8
|
-
* A simple array of anything that responds to <tt>to_s</tt>: <tt>['Date', Time.now].to_csv</tt>
|
9
|
-
* An array of hashes: <tt>[ {'Name' => 'Icaro', 'Age' => 23}, {'Name' => 'Gabriel', 'Age' => 16} ].to_csv</tt>
|
10
|
-
* A matrix: <tt>[['Name', 'Age'], ['Icaro', 23], ['Gabriel', 16]].to_csv</tt>
|
11
|
-
* A hash like array: <tt>[ [['Name', 'Icaro'], ['Age', 23]], [['Name', 'Gabriel'], ['Age', 16]] ].to_csv</tt>
|
12
|
-
* An array of ActiveRecord objects: <tt>@users.to_csv(:except => [:password, :phone], :timestamps => true)</tt>
|
13
|
-
* Scopes in Rails
|
14
|
-
|
15
|
-
|
16
|
-
=== Requirements
|
17
|
-
|
18
|
-
ToCSV has been tested with Ruby 1.8.
|
19
|
-
|
20
|
-
If you are using Ruby 1.9 the only dependency to use the basic features is +ActiveSupport+.
|
21
|
-
Otherwise you will need +fastercsv+. You will receive a warning if you don't meet the requirements.
|
22
|
-
|
23
|
-
# If you don't have Rails installed...
|
24
|
-
$ sudo gem install activesupport
|
25
|
-
|
26
|
-
# And if your Ruby version is lower than 1.9
|
27
|
-
$ sudo gem install fastercsv
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
ToCSV.
|
41
|
-
ToCSV.
|
42
|
-
ToCSV.
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
['
|
59
|
-
]
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
users
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
1
|
+
= ToCSV
|
2
|
+
|
3
|
+
|
4
|
+
ToCSV is a gem for converting arrays or scopes (Rails) to CSV by calling +to_csv+.
|
5
|
+
These arrays can contain different data structures, as long as they are homogeneous, like the ones
|
6
|
+
described below:
|
7
|
+
|
8
|
+
* A simple array of anything that responds to <tt>to_s</tt>: <tt>['Date', Time.now].to_csv</tt>
|
9
|
+
* An array of hashes: <tt>[ {'Name' => 'Icaro', 'Age' => 23}, {'Name' => 'Gabriel', 'Age' => 16} ].to_csv</tt>
|
10
|
+
* A matrix: <tt>[['Name', 'Age'], ['Icaro', 23], ['Gabriel', 16]].to_csv</tt>
|
11
|
+
* A hash like array: <tt>[ [['Name', 'Icaro'], ['Age', 23]], [['Name', 'Gabriel'], ['Age', 16]] ].to_csv</tt>
|
12
|
+
* An array of ActiveRecord objects: <tt>@users.to_csv(:except => [:password, :phone], :timestamps => true)</tt>
|
13
|
+
* Scopes in Rails
|
14
|
+
|
15
|
+
|
16
|
+
=== Requirements
|
17
|
+
|
18
|
+
ToCSV has been tested with Ruby 1.8.7-p299/1.9.1-p378/1.9.2-rc1.
|
19
|
+
|
20
|
+
If you are using Ruby 1.9 the only dependency to use the basic features is +ActiveSupport+.
|
21
|
+
Otherwise you will need +fastercsv+. You will receive a warning if you don't meet the requirements.
|
22
|
+
|
23
|
+
# If you don't have Rails installed...
|
24
|
+
$ sudo gem install activesupport
|
25
|
+
|
26
|
+
# And if your Ruby version is lower than 1.9
|
27
|
+
$ sudo gem install fastercsv
|
28
|
+
|
29
|
+
Full compatibility with Rails 3 is on the way...as well as a new API, with new features.
|
30
|
+
|
31
|
+
|
32
|
+
=== Configuration
|
33
|
+
|
34
|
+
If you want to use this gem with Rails, put the following requirement in your environment.rb:
|
35
|
+
|
36
|
+
config.gem 'to-csv', :lib => 'to_csv', :source => 'http://rubygems.org'
|
37
|
+
|
38
|
+
After that, if you need to globally configure the gem, just create a <i>to_csv.rb</i> file in <i>initializers</i>.
|
39
|
+
|
40
|
+
ToCSV.byte_order_marker = true
|
41
|
+
ToCSV.timestamps = true
|
42
|
+
ToCSV.locale = 'en-US'
|
43
|
+
ToCSV.primary_key = false
|
44
|
+
ToCSV.csv_options[:col_sep] = ','
|
45
|
+
ToCSV.csv_options[:row_sep] = "\r\n"
|
46
|
+
|
47
|
+
|
48
|
+
== Examples
|
49
|
+
|
50
|
+
Let's start with the most simple example.
|
51
|
+
|
52
|
+
['Alfred Hitchcock', 'Robert Mitchum', 'Lucille Ball'].to_csv
|
53
|
+
#=> "Alfred Hitchcock;Robert Mitchum;Lucille Ball\n"
|
54
|
+
|
55
|
+
|
56
|
+
Or, if we have an array of arrays (i.e. a matrix) we can create tabular data.
|
57
|
+
[
|
58
|
+
['Name', 'Gender'],
|
59
|
+
['Alfred', 'M'],
|
60
|
+
['Robert', 'M'],
|
61
|
+
['Lucille', 'F']
|
62
|
+
].to_csv #=> "Name;Gender\nAlfred;M\nRobert;M\nLucille;F\n"
|
63
|
+
|
64
|
+
|
65
|
+
Almost always, when we generate CSV files, we want it to have appropriate
|
66
|
+
headers, so a better approach might be to use an array of hashes.
|
67
|
+
|
68
|
+
[
|
69
|
+
{ 'Name' => 'Alfred', 'Gender' => 'M' },
|
70
|
+
{ 'Name' => 'Robert', 'Gender' => 'M' },
|
71
|
+
{ 'Name' => 'Lucille', 'Gender' => 'F' }
|
72
|
+
].to_csv #=> "Gender;Name\nM;Alfred\nM;Robert\nF;Lucille\n"
|
73
|
+
|
74
|
+
|
75
|
+
Look carefully to the above output. You can see that when we use hashes we can
|
76
|
+
no longer be sure of the headers' order (true for Ruby versions older than 1.9).
|
77
|
+
When we are working with tabular data the headers' order can be very important,
|
78
|
+
thus we can use a somewhat similar data structure:
|
79
|
+
|
80
|
+
[
|
81
|
+
[ ['Name', 'Alfred'], ['Gender', 'M'] ],
|
82
|
+
[ ['Name', 'Robert'], ['Gender', 'M'] ],
|
83
|
+
[ ['Name', 'Lucille'], ['Gender', 'F'] ]
|
84
|
+
].to_csv #=> "Name;Gender\nAlfred;M\nRobert;M\nLucille;F\n"
|
85
|
+
|
86
|
+
That's a lot to type... The first example was much simpler...
|
87
|
+
|
88
|
+
There is the <tt>headers</tt> option. You can use it in all the examples above
|
89
|
+
to enable/disable headers from the output. Default is to show (true).
|
90
|
+
|
91
|
+
users = [{ 'Name' => 'Alfred', 'Gender' => 'M' }]
|
92
|
+
users.to_csv(:headers => false)
|
93
|
+
|
94
|
+
|
95
|
+
==== Active Record Objects
|
96
|
+
|
97
|
+
When we're building our data like the previous examples we have very few options
|
98
|
+
compared to what can be passed when converting an array of AR objects. Again,
|
99
|
+
the easiest way:
|
100
|
+
|
101
|
+
# Anywhere in your app.
|
102
|
+
# By default, all available model attributes (DB columns) are going to be used
|
103
|
+
# except timestamps and the primary key of the record
|
104
|
+
@users = User.all
|
105
|
+
File.open('path/to/file.csv', 'w') { |io| io.puts @users.to_csv }
|
106
|
+
|
107
|
+
|
108
|
+
==== Headers
|
109
|
+
|
110
|
+
You can control the order and the text of any header. You can accomplish that
|
111
|
+
in various ways.
|
112
|
+
|
113
|
+
By default all attribute/method names will be sorted in alphabetical order. So
|
114
|
+
imagine a person model have +name+, +age+ and +email+ as attributes, and you
|
115
|
+
want to get the following output:
|
116
|
+
|
117
|
+
Name | E-mail | Age
|
118
|
+
... | ... | ..
|
119
|
+
... | ... | ..
|
120
|
+
|
121
|
+
You can tell <i>to-csv</i> to use a specific locale. If you don't, it uses
|
122
|
+
your app current locale. It will try to translate attributes to a
|
123
|
+
more friendly text by using the scope <tt>activerecord.attributes.<model name></tt>.
|
124
|
+
If the translation doesn't exist the header's text is going to be humanized.
|
125
|
+
|
126
|
+
The order of columns can be changed with the option +headers+. The way this
|
127
|
+
option works is very similar to the <tt>plugins</tt> method in your Rails
|
128
|
+
<i>environment.rb</i> file.
|
129
|
+
|
130
|
+
* If you pass +nil+ (default) then headers/columns will be in alphabetical order.
|
131
|
+
* If you pass an empty array or +false+, no headers will be shown.
|
132
|
+
* Instead, if you pass a non empty array, headers will be sorted in the order specified. <tt>:all</tt> can be used as a placeholder for all attributes not explicitly named.
|
133
|
+
|
134
|
+
So, in our example above, we can say:
|
135
|
+
|
136
|
+
@users.to_csv(:headers => [:name, :email, :age])
|
137
|
+
|
138
|
+
Or, using the placeholder +all+, which is not very useful here:
|
139
|
+
|
140
|
+
@users.to_csv(:headers => [:name, :email, :all])
|
141
|
+
|
142
|
+
If you want a completely different result you could, for instance, map all
|
143
|
+
users to a hash. Example:
|
144
|
+
|
145
|
+
# This makes use of a hash to completely change the CSV output.
|
146
|
+
@users.map do |user|
|
147
|
+
{
|
148
|
+
'Name' => user.name,
|
149
|
+
'Age' => user.age,
|
150
|
+
'Total Comments' => user.comments.count
|
151
|
+
}
|
152
|
+
end.to_csv
|
153
|
+
|
154
|
+
|
155
|
+
==== Passing a Block
|
156
|
+
|
157
|
+
Sometimes you may want to change just one value out of six for example. The best
|
158
|
+
way to go is to pass a block so that you don't have to repeat yourself writing
|
159
|
+
five headers and it's obvious values and also loosing I18n header translations.
|
160
|
+
|
161
|
+
# The block yields a new Struct for each object in the list. By calling
|
162
|
+
# methods on this struct you can change their default values.
|
163
|
+
@users.to_csv do |row, user|
|
164
|
+
row.date_of_birth = user.date_of_birth.to_s(:long)
|
165
|
+
end
|
166
|
+
|
167
|
+
==== Include Relationships
|
168
|
+
|
169
|
+
If you have an AR object with many relationships and you want to include these to
|
170
|
+
CSV results, you can use :include option.
|
171
|
+
|
172
|
+
Examples:
|
173
|
+
|
174
|
+
# If you want to include a <tt>has_many</tt> relationship, you can do the following:
|
175
|
+
User.all.to_csv(:include => :posts)
|
176
|
+
|
177
|
+
# If you want to include a <tt>belongs_to</tt> relationship:
|
178
|
+
User.all.to_csv(:include => :organization)
|
179
|
+
|
180
|
+
# Or you can use both in the same time.
|
181
|
+
User.all.to_csv(:include => [:organization, :posts])
|
182
|
+
|
183
|
+
==== A More Complete Example
|
184
|
+
|
185
|
+
# users/index.html.haml
|
186
|
+
= link_to 'export (CSV)', users_url(:csv)
|
187
|
+
|
188
|
+
# UsersController#index
|
189
|
+
class UsersController < ApplicationController
|
190
|
+
def index
|
191
|
+
@users = User.most_active
|
192
|
+
respond_to do |format|
|
193
|
+
format.html
|
194
|
+
format.csv do
|
195
|
+
send_data User.csv(@users), :filename => 'users_report.csv'
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# User model
|
202
|
+
class User < ActiveRecord::Base
|
203
|
+
def self.csv(users)
|
204
|
+
users.csv(:headers => [:id, :all], :primary_key => true, :except => :password) do |row, user|
|
205
|
+
row.id = "%04d" % user.id
|
206
|
+
row.created_at = I18n.l(user.created_at, :format => :default)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# locales/en-US.yml
|
212
|
+
activerecord:
|
213
|
+
attributes:
|
214
|
+
user:
|
215
|
+
id: Code
|
216
|
+
|
217
|
+
==== Full Customization
|
218
|
+
|
219
|
+
You can always customize the output if you wish by building arrays of hashes,
|
220
|
+
arrays of arrays of bidimensional arrays etc :). Or you can obviously mix
|
221
|
+
anything you want and even use FasterCSV directly.
|
222
|
+
|
223
|
+
@user.to_csv { :only => [:name, :email] }, :col_sep => ','
|
224
|
+
|
225
|
+
There are other options for you to customize the output. Take a look at the
|
226
|
+
<tt>to_csv</tt> method documentation.
|
227
|
+
|
228
|
+
==== Credits
|
229
|
+
|
230
|
+
Special thanks to these people for their contributions and/or ideas:
|
231
|
+
|
232
|
+
* {Kyle J. Ginavan}[http://github.com/kylejginavan]
|
233
|
+
* {Mauro Torres}[http://github.com/chebyte]
|
234
|
+
* {petRUShka}[http://github.com/petRUShka]
|
235
|
+
|
236
|
+
Copyright (c) 2010 Ícaro Leopoldino da Motta, released under the MIT license.
|
237
|
+
|