to-csv 1.0.2 → 1.0.3

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.
@@ -1,15 +1,21 @@
1
- == 1.0.2 2010-01-04
2
-
3
- * Changed use of OpenStruct in favor of Struct, which supports any attribute name. Now a block yields a Struct and the object itself
4
- * Support for Rails scopes
5
- * Improved documentation
6
-
7
- == 1.0.1 2009-12-24
8
-
9
- * Now compatible with Ruby 1.9.1
10
- * Updated documentation to reflect Ruby 1.9.1 support
11
-
12
- == 1.0.0 2009-12-23
13
-
14
- * First release
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
+
@@ -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.
@@ -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.6/1.8.7/1.9.1.
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
- === Configuration
31
-
32
- If you want to use this gem with Rails, put the following requirement in your environment.rb:
33
-
34
- config.gem 'to-csv', :lib => 'to_csv', :source => 'http://gemcutter.org'
35
-
36
- After that, if you need to globally configure the gem, just create a <i>to_csv.rb</i> file in <i>initializers</i>.
37
-
38
- ToCSV.byte_order_marker = true
39
- ToCSV.timestamps = true
40
- ToCSV.locale = 'en-US'
41
- ToCSV.primary_key = false
42
- ToCSV.csv_options = { :col_sep => ',', :row_sep => "\r\n" }
43
-
44
-
45
- == Examples
46
-
47
- Let's start with the most simple example.
48
-
49
- ['Alfred Hitchcock', 'Robert Mitchum', 'Lucille Ball'].to_csv
50
- #=> "Alfred Hitchcock;Robert Mitchum;Lucille Ball\n"
51
-
52
-
53
- Or, if we have an array of arrays (i.e. a matrix) we can create tabular data.
54
- [
55
- ['Name', 'Gender'],
56
- ['Alfred', 'M'],
57
- ['Robert', 'M'],
58
- ['Lucille', 'F']
59
- ].to_csv #=> "Name;Gender\nAlfred;M\nRobert;M\nLucille;F\n"
60
-
61
-
62
- Almost always, when we generate CSV files, we want it to have appropriate
63
- headers, so a better approach might be to use an array of hashes.
64
-
65
- [
66
- { 'Name' => 'Alfred', 'Gender' => 'M' },
67
- { 'Name' => 'Robert', 'Gender' => 'M' },
68
- { 'Name' => 'Lucille', 'Gender' => 'F' }
69
- ].to_csv #=> "Gender;Name\nM;Alfred\nM;Robert\nF;Lucille\n"
70
-
71
-
72
- Look carefully to the above output. You can see that when we use hashes we can
73
- no longer be sure of the headers' order (true for Ruby versions older than 1.9).
74
- When we are working with tabular data the headers' order can be very important,
75
- thus we can use a somewhat similar data structure:
76
-
77
- [
78
- [ ['Name', 'Alfred'], ['Gender', 'M'] ],
79
- [ ['Name', 'Robert'], ['Gender', 'M'] ],
80
- [ ['Name', 'Lucille'], ['Gender', 'F'] ]
81
- ].to_csv #=> "Name;Gender\nAlfred;M\nRobert;M\nLucille;F\n"
82
-
83
- That's a lot to type... The first example was much simpler...
84
-
85
- There is the <tt>headers</tt> option. You can use it in all the examples above
86
- to enable/disable headers from the output. Default is to show (true).
87
-
88
- users = [{ 'Name' => 'Alfred', 'Gender' => 'M' }]
89
- users.to_csv(:headers => false)
90
-
91
-
92
- ==== Active Record Objects
93
-
94
- When we're building our data like the previous examples we have very few options
95
- compared to what can be passed when converting an array of AR objects. Again,
96
- the easiest way:
97
-
98
- # Anywhere in your app.
99
- # By default, all available model attributes (DB columns) are going to be used
100
- # except timestamps and the primary key of the record
101
- @users = User.all
102
- File.open('path/to/file.csv', 'w') { |io| io.puts @users.to_csv }
103
-
104
-
105
- ==== Headers
106
-
107
- You can control the order and the text of any header. You can accomplish that
108
- in various ways.
109
-
110
- By default all attribute/method names will be sorted in alphabetical order. So
111
- imagine a person model have +name+, +age+ and +email+ as attributes, and you
112
- want to get the following output:
113
-
114
- Name | E-mail | Age
115
- ... | ... | ..
116
- ... | ... | ..
117
-
118
- You can tell <i>to-csv</i> to use a specific locale. If you don't, it uses
119
- your app current locale. It will try to translate attributes to a
120
- more friendly text by using the scope <tt>[:activerecord, :attributes, <model name>]</tt>.
121
- If the translation doesn't exist the header's text is going to be humanized.
122
-
123
- The order of columns can be changed with the option +headers+. The way this
124
- option works is very similar to the <tt>plugins</tt> method in your Rails
125
- <i>environment.rb</i> file.
126
-
127
- * If you pass +nil+ (default) then headers/columns will be in alphabetical order.
128
- * If you pass an empty array or +false+, no headers will be shown.
129
- * 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.
130
-
131
- So, in our example above, we can say:
132
-
133
- @users.to_csv(:headers => [:name, :email, :age])
134
-
135
- Or, using the placeholder +all+, which is not very useful here:
136
-
137
- @users.to_csv(:headers => [:name, :email, :all])
138
-
139
- If you want a completely different result you could, for instance, map all
140
- users to a hash. Example:
141
-
142
- # This makes use of a hash to completely change the CSV output.
143
- @users.map do |user|
144
- {
145
- 'Name' => user.name,
146
- 'Age' => user.age,
147
- 'Total Comments' => user.comments.count
148
- }
149
- end.to_csv
150
-
151
-
152
- ===== Passing a Block
153
-
154
- Sometimes you may want to change just one value out of six for example. The best
155
- way to go is to pass a block so that you don't have to repeat yourself writing
156
- five headers and it's obvious values and also loosing I18n header translations.
157
-
158
- # The block yields a new Struct for each object in the list. By calling
159
- # methods on this struct you can change their default values.
160
- @users.to_csv do |row, user|
161
- row.date_of_birth = user.date_of_birth.to_s(:long)
162
- end
163
-
164
-
165
- ===== A More Complete Example
166
-
167
- # users/index.html.haml
168
- = link_to 'export (CSV)', users_url(:csv)
169
-
170
- # UsersController#index
171
- class UsersController < ApplicationController
172
- def index
173
- @users = User.most_active
174
- respond_to do |format|
175
- format.html
176
- format.csv do
177
- send_data User.csv(@users), :filename => 'users_report.csv'
178
- end
179
- end
180
- end
181
- end
182
-
183
- # User model
184
- class User < ActiveRecord::Base
185
- def self.csv(users)
186
- users.csv(:headers => [:id, :all], :primary_key => true, :except => :password) do |row, user|
187
- row.id = "%04d" % user.id
188
- row.created_at = I18n.l(user.created_at, :format => :default)
189
- end
190
- end
191
- end
192
-
193
- # locales/en-US.yml
194
- activerecord:
195
- attributes:
196
- user:
197
- id: Code
198
-
199
-
200
- ==== Full Customization
201
-
202
- You can always customize the output if you wish by building arrays of hashes,
203
- arrays of arrays of bidimensional arrays etc :). Or you can obviously mix
204
- anything you want and even use FasterCSV directly.
205
-
206
- @user.to_csv { :only => [:name, :email] }, :col_sep => ','
207
-
208
- There are other options for you to customize the output. Take a look at the
209
- <tt>to_csv</tt> method documentation.
210
-
211
- Copyright (c) 2009 Ícaro Leopoldino da Motta, released under the MIT license.
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
+