to-csv 1.0.1 → 1.0.2

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