csv_rb 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/Gemfile +24 -0
  4. data/Gemfile.lock +250 -0
  5. data/Guardfile +16 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +510 -0
  8. data/Rakefile +29 -0
  9. data/lib/csv_rb/action_controller.rb +66 -0
  10. data/lib/csv_rb/plain_builder.rb +27 -0
  11. data/lib/csv_rb/railtie.rb +16 -0
  12. data/lib/csv_rb/stream_csv_deflator.rb +25 -0
  13. data/lib/csv_rb/template_handler.rb +31 -0
  14. data/lib/csv_rb/version.rb +5 -0
  15. data/lib/csv_rb.rb +6 -0
  16. data/lib/tasks/csv_rb_tasks.rake +4 -0
  17. data/spec/ci.rb +4 -0
  18. data/spec/csv_rb_builder_spec.rb +39 -0
  19. data/spec/csv_rb_mailer_spec.rb +17 -0
  20. data/spec/csv_rb_renderer_spec.rb +18 -0
  21. data/spec/csv_rb_request_spec.rb +220 -0
  22. data/spec/dummy/Rakefile +6 -0
  23. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  24. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  25. data/spec/dummy/app/controllers/application_controller.rb +7 -0
  26. data/spec/dummy/app/controllers/home_controller.rb +58 -0
  27. data/spec/dummy/app/controllers/likes_controller.rb +20 -0
  28. data/spec/dummy/app/controllers/users_controller.rb +39 -0
  29. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  30. data/spec/dummy/app/mailers/notifier.rb +14 -0
  31. data/spec/dummy/app/models/like.rb +3 -0
  32. data/spec/dummy/app/models/user.rb +24 -0
  33. data/spec/dummy/app/views/home/_cover_sheet.csv.csvrb +1 -0
  34. data/spec/dummy/app/views/home/index.csv.csvrb +2 -0
  35. data/spec/dummy/app/views/home/index.html.erb +4 -0
  36. data/spec/dummy/app/views/home/only_html.html.erb +2 -0
  37. data/spec/dummy/app/views/home/useheader.csv.csvrb +1 -0
  38. data/spec/dummy/app/views/home/withpartial.csv.csvrb +2 -0
  39. data/spec/dummy/app/views/layouts/application.html.erb +12 -0
  40. data/spec/dummy/app/views/layouts/users.html.erb +12 -0
  41. data/spec/dummy/app/views/likes/index.csv.csvrb +4 -0
  42. data/spec/dummy/app/views/likes/index.html.erb +17 -0
  43. data/spec/dummy/app/views/notifier/instructions.html.erb +14 -0
  44. data/spec/dummy/app/views/notifier/instructions.txt.erb +6 -0
  45. data/spec/dummy/app/views/users/export.csv.csvrb +1 -0
  46. data/spec/dummy/app/views/users/index.csv.csvrb +1 -0
  47. data/spec/dummy/app/views/users/index.html.erb +23 -0
  48. data/spec/dummy/app/views/users/noaction.csv.csvrb +1 -0
  49. data/spec/dummy/app/views/users/respond_with.csv.csvrb +1 -0
  50. data/spec/dummy/app/views/users/send_instructions.csv.csvrb +2 -0
  51. data/spec/dummy/bin/bundle +3 -0
  52. data/spec/dummy/bin/rails +4 -0
  53. data/spec/dummy/bin/rake +4 -0
  54. data/spec/dummy/config/application.rb +22 -0
  55. data/spec/dummy/config/boot.rb +5 -0
  56. data/spec/dummy/config/database.yml +25 -0
  57. data/spec/dummy/config/environment.rb +5 -0
  58. data/spec/dummy/config/environments/development.rb +37 -0
  59. data/spec/dummy/config/environments/production.rb +83 -0
  60. data/spec/dummy/config/environments/test.rb +40 -0
  61. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  62. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  63. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  64. data/spec/dummy/config/initializers/inflections.rb +16 -0
  65. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  66. data/spec/dummy/config/initializers/secret_token.rb +2 -0
  67. data/spec/dummy/config/initializers/session_store.rb +3 -0
  68. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  69. data/spec/dummy/config/locales/en.yml +23 -0
  70. data/spec/dummy/config/routes.rb +17 -0
  71. data/spec/dummy/config/secrets.yml +22 -0
  72. data/spec/dummy/config.ru +4 -0
  73. data/spec/dummy/db/development.sqlite3 +0 -0
  74. data/spec/dummy/db/migrate/20120717192452_create_users.rb +12 -0
  75. data/spec/dummy/db/migrate/20121206210955_create_likes.rb +10 -0
  76. data/spec/dummy/db/schema.rb +31 -0
  77. data/spec/dummy/db/test.sqlite3 +0 -0
  78. data/spec/dummy/log/development.log +257 -0
  79. data/spec/dummy/log/test.log +25347 -0
  80. data/spec/dummy/public/404.html +67 -0
  81. data/spec/dummy/public/422.html +67 -0
  82. data/spec/dummy/public/500.html +66 -0
  83. data/spec/dummy/public/favicon.ico +0 -0
  84. data/spec/reset_gems.sh +2 -0
  85. data/spec/spec_helper.rb +39 -0
  86. data/spec/test_5.2.sh +16 -0
  87. data/spec/test_all_rails.sh +4 -0
  88. data/spec/test_revert.sh +3 -0
  89. metadata +413 -0
data/README.md ADDED
@@ -0,0 +1,510 @@
1
+ csvrb-Rails — Spreadsheet templates for Rails
2
+ ===================================================
3
+
4
+ [![Build Status](https://secure.travis-ci.org/straydogstudio/csv_rb.svg?branch=master)](http://travis-ci.org/straydogstudio/csv_rb)
5
+ [![Gem
6
+ Version](https://badge.fury.io/rb/csv_rb.svg)](http://badge.fury.io/rb/csv_rb)
7
+ [![Dependency Status](https://gemnasium.com/straydogstudio/csv_rb.svg?branch=master)](https://gemnasium.com/straydogstudio/csv_rb)
8
+ [![Coverage
9
+ Status](https://coveralls.io/repos/straydogstudio/csv_rb/badge.svg)](https://coveralls.io/r/straydogstudio/csv_rb)
10
+
11
+ ![Total downloads](http://ruby-gem-downloads-badge.herokuapp.com/csv_rb?type=total)
12
+ ![Downloads for 0.4.0](http://ruby-gem-downloads-badge.herokuapp.com/csv_rb/0.4.0?label=0.4.0)
13
+ ![Downloads for 0.5.0](http://ruby-gem-downloads-badge.herokuapp.com/csv_rb/0.5.0?label=0.5.0)
14
+ ![Downloads for latest release](http://ruby-gem-downloads-badge.herokuapp.com/csv_rb/0.5.1?label=0.5.1)
15
+
16
+ ## Installation
17
+
18
+ In your Gemfile:
19
+
20
+ ```ruby
21
+ gem 'rubyzip', '>= 1.2.1'
22
+ gem 'csvrb', git: 'https://github.com/randym/csvrb.git', ref: 'c8ac844'
23
+ gem 'csv_rb'
24
+ ```
25
+
26
+ **NOTE:** csvrb has been pending release for a long time. You must specify the master on github to support Rubyzip 1.2.1.
27
+
28
+ If `rubyzip 1.0.0` is needed:
29
+
30
+ ```ruby
31
+ gem 'rubyzip', '= 1.0.0'
32
+ gem 'csvrb', '= 2.0.1'
33
+ gem 'csv_rb'
34
+ ```
35
+
36
+ If `rubyzip >= 1.1.0` is needed:
37
+
38
+ ```ruby
39
+ gem 'rubyzip', '~> 1.1.0'
40
+ gem 'csvrb', '2.1.0.pre'
41
+ gem 'csv_rb'
42
+ ```
43
+
44
+ ## Requirements
45
+
46
+ * Rails 4.2, 5.0 or 5.1 (tested)
47
+ * For Rails 3.1 or 3.2 use version 3.0
48
+ * **As of 0.5.0 requires csvrb 2.0.1, but strongly suggests 2.1.0.pre, which requires rubyzip 1.1.0**
49
+ * As of Rails 4.1 you must use `render_to_string` to render a mail attachment.
50
+
51
+ ## FYI
52
+
53
+ * This gem depends on [csvrb](https://github.com/randym/csvrb). See [the blog](http://csvrb.blog.randym.net/) or the [examples page](https://github.com/randym/csvrb/blob/master/examples/example.rb) for usage.
54
+ * Check out [csvrb_styler](https://github.com/sakovias/csvrb_styler) by [sakovias](https://github.com/sakovias) for easier styles and borders!
55
+
56
+ ## Usage
57
+
58
+ csvrb-Rails provides a renderer and a template handler. It adds the `:csv` format and parses `.csv.csvrb` templates. This lets you take all the [csvrb](https://github.com/randym/csvrb) code out of your controller or model and place it inside the template, where view code belongs! **See [this blog post](http://csvrb.blog.randym.net/2012/08/excel-on-rails-like-pro-with-CSVRb.html) for a more complete walkthrough.**
59
+
60
+ ### Controller
61
+
62
+ To use csvrb-Rails set your instance variables in your controller and configure the response if needed:
63
+
64
+ ```ruby
65
+ class ButtonController < ApplicationController
66
+ def action_name
67
+ @buttons = Button.all
68
+ respond_to do |format|
69
+ format.csv
70
+ end
71
+ end
72
+ end
73
+ ```
74
+
75
+ ### Template
76
+
77
+ Create the template with the `.csv.csvrb` extension (`action_name.csv.csvrb` for example.) [**Watch out for typos!**](#troubleshooting) In the template, use csv_package variable to create your spreadsheet:
78
+
79
+ ```ruby
80
+ wb = csv_package.workbook
81
+ wb.add_worksheet(name: "Buttons") do |sheet|
82
+ @buttons.each do |button|
83
+ sheet.add_row [button.name, button.category, button.price]
84
+ end
85
+ end
86
+ ```
87
+
88
+ This is where you place all your [csvrb](https://github.com/randym/csvrb) specific markup. Add worksheets, fill content, merge cells, add styles. See the [csvrb examples](https://github.com/randym/csvrb/tree/master/examples/example.rb) page to see what you can do.
89
+
90
+ Remember, like in `erb` templates, view helpers are available to use the `.csv.csvrb` template.
91
+
92
+ That's it. Call your action and your spreadsheet will be delivered.
93
+
94
+ ### Rendering Options
95
+
96
+ You can call render in any of the following ways:
97
+
98
+ ```ruby
99
+ # rendered, no disposition/filename header
100
+ render 'buttons'
101
+ # rendered from another controller, no disposition/filename header
102
+ render 'featured/latest'
103
+ # template and filename of 'buttons'
104
+ render csv: 'buttons'
105
+ # template from another controller, filename of 'latest_buttons'
106
+ render csv: 'latest_buttons', template: 'featured/latest'
107
+ ```
108
+
109
+ ### Disposition
110
+
111
+ To specify a disposition (such as `inline` so the spreadsheet is opened inside the browser), use the `disposition` option:
112
+
113
+ ```ruby
114
+ render csv: "buttons", disposition: 'inline'
115
+ ```
116
+
117
+ If `render csv:` is called, the disposition defaults to `attachment`.
118
+
119
+ ### File name
120
+
121
+ If Rails calls csvrb through default channels (because you use `format.csv {}` for example) you must set the filename using the response header:
122
+
123
+ ```ruby
124
+ format.csv {
125
+ response.headers['Content-Disposition'] = 'attachment; filename="my_new_filename.csv"'
126
+ }
127
+ ```
128
+
129
+ If you use `render csv:` the gem will try to guess the file name:
130
+
131
+ ```ruby
132
+ # filename of 'buttons'
133
+ render csv: 'buttons'
134
+ # filename of 'latest_buttons'
135
+ render csv: 'latest_buttons', template: 'featured/latest'
136
+ ```
137
+
138
+ If that fails, pass the `:filename` parameter:
139
+
140
+ ```ruby
141
+ render csv: "action_or_template", filename: "my_new_filename.csv"
142
+ ```
143
+
144
+ ### csv_rb Package Options
145
+
146
+ csv_rb provides three options for initializing a spreadsheet:
147
+
148
+ - **:csv_author** (String) - The author of the document
149
+ - **:csv_created_at** (Time) - Timestamp in the document properties (defaults to current time)
150
+ - **:csv_use_shared_strings** (Boolean) - This is passed to the workbook to specify that shared strings should be used when serializing the package.
151
+
152
+ To pass these to the new package, pass them to `render :csv` _or_ pass them as local variables.
153
+
154
+ For example, to set the author name, pass the `:csv_author` parameter to `render :csv` _or_ as a local variable:
155
+
156
+ ```ruby
157
+ render csv: "index", csv_author: "Elmer Fudd"
158
+ render "index", locals: {csv_author: "Elmer Fudd"}
159
+ ```
160
+
161
+ Other examples:
162
+
163
+ ```ruby
164
+ render csv: "index", csv_created_at: 3.days.ago
165
+ render "index", locals: {csv_use_shared_strings: true}
166
+ ```
167
+
168
+ ### Partials
169
+
170
+ Partials work as expected, but you must pass in relevant spreadsheet variables:
171
+
172
+ ```ruby
173
+ wb = csv_package.workbook
174
+ render :partial => 'cover_sheet', :locals => {:wb => wb}
175
+ wb.add_worksheet(name: "Content") do |sheet|
176
+ sheet.add_row ['Content']
177
+ end
178
+ ```
179
+
180
+ With the partial simply using the passed variables:
181
+
182
+ ```ruby
183
+ wb.add_worksheet(name: "Cover Sheet") do |sheet|
184
+ sheet.add_row ['Cover', 'Sheet']
185
+ end
186
+ ```
187
+
188
+ ### Mailers
189
+
190
+ To use an csv template to render a mail attachment, use the following syntax:
191
+
192
+ ```ruby
193
+ class UserMailer < ActionMailer::Base
194
+ def export(users)
195
+ csv = render_to_string layout: false, handlers: [:csvrb], formats: [:csv], template: "users/export", locals: {users: users}
196
+ attachment = Base64.encode64(csv)
197
+ attachments["Users.csv"] = {mime_type: Mime[:csv], content: attachment, encoding: 'base64'}
198
+ # For rails 4 use Mime::csv
199
+ # attachments["Users.csv"] = {mime_type: Mime::csv, content: attachment, encoding: 'base64'}
200
+ # self.instance_variable_set(:@_lookup_context, nil) # If attachments are rendered as content, try this and open an issue
201
+ ...
202
+ end
203
+ end
204
+ ```
205
+
206
+ * If the route specifies or suggests the `:csv` format you do not need to specify `formats` or `handlers`.
207
+ * If the template (`users/export`) can refer to only one file (the csv.csvrb template), you do not need to specify `handlers`, provided the `formats` includes `:csv`.
208
+ * Specifying the encoding as 'base64' can avoid UTF-8 errors.
209
+
210
+ ### Scripts
211
+
212
+ To generate a template within a script, you need to instantiate an ActionView context. Here are two gists showing how to perform this:
213
+
214
+ * [Using rails runner](https://gist.github.com/straydogstudio/323139591f2cc5d48fbc)
215
+ * [Without rails runner](https://gist.github.com/straydogstudio/dceb775ead81470cea70)
216
+
217
+ ### Testing
218
+
219
+ There is no built-in way to test your resulting workbooks / templates. But here is a piece of code that may help you to find a way.
220
+
221
+ #### First, create a shared context
222
+
223
+ ```ruby
224
+ RSpec.shared_context 'csvrb' do
225
+
226
+ # all csv specs describe must be normalized
227
+ # "folder/view_name.csv.csvrb"
228
+ # allow to infer the template path
229
+ template_name = description
230
+
231
+ let(:template_path) do
232
+ ['app', 'views', template_name]
233
+ end
234
+
235
+ # This helper will be used in tests
236
+ def render_template(locals = {})
237
+ csvrb_binding = Kernel.binding
238
+ locals.each do |key, value|
239
+ csvrb_binding.local_variable_set key, value
240
+ end
241
+ # define a default workbook and a default sheet useful when testing partial in isolation
242
+ wb = CSVRb::Package.new.workbook
243
+ csvrb_binding.local_variable_set(:wb, wb)
244
+ csvrb_binding.local_variable_set(:sheet, wb.add_worksheet)
245
+
246
+ # mimics an ActionView::Template class, presenting a 'source' method
247
+ # to retrieve the content of the template
248
+ csvrb_binding.eval(ActionView::Template::Handlers::CSVRbBuilder.call(Struct.new(:source).new(File.read(Rails.root.join(*template_path)))))
249
+ csvrb_binding.local_variable_get(:wb)
250
+ end
251
+ end
252
+ ```
253
+
254
+ #### Include it in your spec files:
255
+
256
+ ```ruby
257
+ require 'spec_helper'
258
+ require 'helpers/csvrb_context'
259
+
260
+ describe 'shared/_total_request.csv.csvrb' do
261
+ include_context 'csvrb'
262
+
263
+ before :each do
264
+ # all the instance variables here are the one used in 'shared/_total_request.csv.csvrb'
265
+ @widget = mock_model(Widget, name: 'My widget')
266
+ @message_counts = Struct.new(:count_all, :positives, :negatives, :neutrals).new(42, 23, 15, 25)
267
+ end
268
+
269
+ it 'has a title line mentioning the widget' do
270
+ wb = render_template
271
+ sheet = wb.sheet_by_name('Réf. Requête')
272
+ expect(sheet).to have_header_cells ['My widget : Messages de la requête']
273
+ end
274
+
275
+ it 'exports the message counts' do
276
+ wb = render_template
277
+ sheet = wb.sheet_by_name('Réf. Requête')
278
+ expect(sheet).to have_cells(['Toutes tonalités', 'Tonalité positive', 'Tonalité négative', 'Tonalité neutre']).in_row(2)
279
+ expect(sheet).to have_cells([42, 23, 15, 25]).in_row(3)
280
+ end
281
+
282
+ end
283
+ ```
284
+
285
+ #### Matchers used
286
+
287
+ ```ruby
288
+
289
+ # encoding: UTF-8
290
+
291
+ require 'rspec/expectations'
292
+
293
+ module XslsMatchers
294
+
295
+ RSpec::Matchers.define :have_header_cells do |cell_values|
296
+ match do |worksheet|
297
+ worksheet.rows[0].cells.map(&:value) == cell_values
298
+ end
299
+
300
+ failure_message do |actual|
301
+ "Expected #{actual.rows[0].cells.map(&:value)} to be #{expected}"
302
+ end
303
+ end
304
+
305
+ RSpec::Matchers.define :have_cells do |expected|
306
+ match do |worksheet|
307
+ worksheet.rows[@index].cells.map(&:value) == expected
308
+ end
309
+
310
+ chain :in_row do |index|
311
+ @index = index
312
+ end
313
+
314
+ failure_message do |actual|
315
+ "Expected #{actual.rows[@index].cells.map(&:value)} to include #{expected} at row #{@index}."
316
+ end
317
+ end
318
+ end
319
+
320
+ ```
321
+
322
+
323
+ ## Troubleshooting
324
+
325
+ ### Mispellings
326
+
327
+ **It is easy to get the spelling wrong in the extension name, the format.csv statement, or in a render call.** Here are some possibilities:
328
+
329
+ * If it says your template is missing, check that its extension is `.csv.csvrb`.
330
+ * If you get the error `uninitialized constant Mime::XSLX` you have used `format.xslx` instead of `format.csv`, or something similar.
331
+
332
+ ### Mailer Attachments: No content, cannot read, Invalid Byte Sequence in UTF-8
333
+
334
+ If you are having problems with rendering a template and attaching it to a template, try a few options:
335
+
336
+ * Make sure the attachment template does not have the same name as the mailer.
337
+ * After you have rendered the template to string, and before you call the mailer, execute `self.instance_variable_set(:@_lookup_context, nil)`. If you must do this, please open an issue.
338
+ * If you get Invalid Byte Sequence in UTF-8, pass `encoding: 'base64'` with the attachment:
339
+
340
+ ```ruby
341
+ class UserMailer < ActionMailer::Base
342
+ def export(users)
343
+ csv = render_to_string handlers: [:csvrb], formats: [:csv], template: "users/export", locals: {users: users}
344
+ attachments["Users.csv"] = {mime_type: Mime[:csv], content: csv, encoding: 'base64'}
345
+ # For Rails 4 use Mime::csv
346
+ # attachments["Users.csv"] = {mime_type: Mime::csv, content: csv, encoding: 'base64'}
347
+ # self.instance_variable_set(:@_lookup_context, nil) # If attachments are rendered as content, try this and open an issue
348
+ ...
349
+ end
350
+ end
351
+ ```
352
+
353
+ If you get these errors, please open an issue and share code so the bug can be isolated. Or comment on issue [#29](https://github.com/straydogstudio/csv_rb/issues/29) or [#25](https://github.com/straydogstudio/csv_rb/issues/25).
354
+
355
+ ### Generated Files Can't Be Opened or Invalid Byte Sequence in UTF-8
356
+
357
+ Both these errors *appear* to be caused by Rails applying a layout to the template. Passing `layout: false` to `render :csv` should fix this issue. Version 0.5.0 attempts to fix this issue.
358
+
359
+ If you get this error, please open an issue and share code so the bug can be isolated.
360
+
361
+ ### Rails 4.2 changes
362
+
363
+ Before Rails 4.2 you could call:
364
+
365
+ ```ruby
366
+ render csv: "users/index"
367
+ ```
368
+
369
+ And csv_rb could adjust the paths and make sure the template was loaded from the right directory. This is no longer possible because the paths are cached between requests for a given controller. As a result, to display a template in another directory you must use the `:template` parameter (which is normal Rails behavior anyway):
370
+
371
+ ```ruby
372
+ render csv: "index", template: "users/index"
373
+ ```
374
+
375
+ If the request format matches you should be able to call:
376
+
377
+ ```ruby
378
+ render "users/index"
379
+ ```
380
+
381
+ This is a breaking change if you have the old syntax!
382
+
383
+ ### Turbolinks
384
+
385
+ If you are using turbolinks, you may need to disable turbolinks when you link to your spreadsheet:
386
+
387
+ ```ruby
388
+ # turbolinks 5:
389
+ link_to 'Download spreadsheet', path_to_sheet, data: {turbolinks: false}
390
+ ```
391
+
392
+ ### What to do
393
+
394
+ If you are having problems, try to isolate the issue. Use the console or a script to make sure your data is good. Then create the spreadsheet line by line without csvrb-Rails to see if you are having csvrb problems. If you can manually create the spreadsheet, create an issue and we will work it out.
395
+
396
+ ## Dependencies
397
+
398
+ - [Rails](https://github.com/rails/rails)
399
+ - [csvrb](https://github.com/randym/csvrb)
400
+
401
+ ## Authors
402
+
403
+ * [Noel Peden](https://github.com/straydogstudio)
404
+
405
+ ## Contributors
406
+
407
+ Many thanks to [contributors](https://github.com/straydogstudio/csv_rb/graphs/contributors):
408
+
409
+ * [randym](https://github.com/randym)
410
+ * [sugi](https://github.com/sugi)
411
+ * [envek](https://github.com/envek)
412
+ * [engwan](https://github.com/engwan)
413
+ * [maxd](https://github.com/maxd)
414
+ * [firien](https://github.com/firien)
415
+ * [kaluzny](https://github.com/kaluznyo)
416
+ * [sly7-7](https://github.com/sly7-7)
417
+ * [kodram](https://github.com/kodram)
418
+ * [JohnSmall](https://github.com/JohnSmall)
419
+ * [BenoitHiller](https://github.com/BenoitHiller)
420
+
421
+ ## Donations
422
+
423
+ Say thanks for csvrb-Rails by donating! It makes it easier for me to provide to open
424
+ source:
425
+
426
+ [![Click here to lend your support to: csvrb-Rails!](http://www.pledgie.com/campaigns/27737.png?skin_name=chrome)](http://www.pledgie.com/campaigns/27737)
427
+
428
+ ## Change log
429
+
430
+ **May 1st, 2018**: 0.5.2 release
431
+
432
+ - Improved Rails 5 compatibility re MIME type
433
+
434
+ **March 29th, 2017**: 0.5.1 release
435
+
436
+ - Fix stack trace line numbers
437
+ - Thanks to [BenoitHiller](https://github.com/BenoitHiller)
438
+
439
+ **July 26st, 2016**: 0.5.0 release
440
+
441
+ - Support for Rails 5
442
+ - **Tested on on Rails 4.0, 4.1, 4.2, and 5.0**
443
+ - Bug fixes for unreadable files and UTF-8 errors
444
+
445
+ **July 13th, 2015**: 0.4.0 release
446
+
447
+ - Support for Rails 4.2
448
+ - **Removal of forced default_formats** (url format must match)
449
+ - **Tested only on Rails 4.1 and 4.2**
450
+ - **For Rails 3.2 or below, use 0.3.0**
451
+
452
+ **November 20th, 2014**: 0.3.0 release
453
+
454
+ - Support for Rails 4.2.beta4.
455
+ - **Removal of shorthand template syntax** (`render csv: 'another/directory'`)
456
+
457
+ **September 4, 2014**: 0.2.1 release
458
+
459
+ - Rails 4.2.beta1 no longer includes responder. This release checks for the existence of responder before configuring a default responder.
460
+ - Rails 4.2 testing, though not yet on Travis CI
461
+ - Author, created_at, and use_shared_strings parameters for CSVRb::Package.new
462
+
463
+ **April 9, 2014**: 0.2.0 release
464
+
465
+ - Require csvrb 2.0.1, which requires rubyzip 1.0.0
466
+ - Better render handling and testing, which might break former usage
467
+ - Rails 4.1 testing
468
+ - Mailer example update (**use render_to_string not render**)
469
+
470
+ **October 11, 2013**
471
+
472
+ - Handle (and test) respond_to override
473
+
474
+ **October 4, 2013**
475
+
476
+ - Added coveralls
477
+ - Raised testing to csvrb 2.0.1, roo 1.12.2, and rubyzip 1.0.0
478
+
479
+ **July 25, 2013**
480
+
481
+ - Documentation improved
482
+ - Testing for generating partial in mailer
483
+
484
+ **January 18, 2013**: 0.1.4 release
485
+
486
+ - Now supports Rails 4 (thanks [Envek](https://github.com/Envek))
487
+ - If you call render :csv on a request without :csv format, it should force the :csv format. Works on Rails 3.2+.
488
+
489
+ **December 6, 2012**: 0.1.3 release
490
+
491
+ - Fix for absolute template paths
492
+
493
+ **July 25, 2012**: 0.1.2 release
494
+
495
+ - Partials tested
496
+
497
+ **July 19, 2012**: 0.1.1 release
498
+
499
+ - Travis-ci added (thanks [randym](https://github.com/randym))
500
+ - render statements and filename tests fixes (thanks [engwan](https://github.com/engwan))
501
+
502
+ **July 17, 2012**: 0.1.0 release
503
+
504
+ - Tests completed
505
+ - Acts_as_csv tested, example in docs
506
+
507
+ **July 12, 2012**: 0.0.1 release
508
+
509
+ - Initial posting.
510
+ - It works, but there are no tests! Bad programmer!
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'CSVRb'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ require "rspec/core/rake_task"
24
+ RSpec::Core::RakeTask.new('spec')
25
+
26
+ task :default => :spec
27
+
28
+ Bundler::GemHelper.install_tasks
29
+
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_controller'
4
+ require 'csv_rb/stream_csv_deflator'
5
+ unless Mime[:csv]
6
+ Mime::Type.register 'text/csv', :csv
7
+ end
8
+
9
+ ActionController::Renderers.add :csv do |filename, options|
10
+ #
11
+ # You can always specify a template:
12
+ #
13
+ # def called_action
14
+ # render csv: 'filename', template: 'controller/diff_action'
15
+ # end
16
+ #
17
+ # And the normal use case works:
18
+ #
19
+ # def called_action
20
+ # render 'diff_action'
21
+ # # or
22
+ # render 'controller/diff_action'
23
+ # end
24
+ #
25
+ options[:template] = filename.gsub(/^.*\//,'') if options[:template] == action_name
26
+ options[:template] = "#{options[:template]}.csv.csvrb" unless options[:template] =~ /\.csvrb/
27
+ options[:layout] = false
28
+ options[:locals] ||= {}
29
+ file_name = "#{options.delete(:filename) || filename.gsub(/^.*\//,'')}#{options.delete(:with_time) ? "-#{Time.zone.now.to_s}" : ''}.csv".sub(/(\.csv)+$/, '.csv')
30
+
31
+
32
+ # if options.delete(:should_stream)
33
+ response.headers["X-Accel-Buffering"] = 'no'
34
+ response.headers["Content-Type"] = "text/csv; charset=utf-8"
35
+ response.headers["Content-Encoding"] = 'deflate'
36
+ response.headers["Content-Disposition"] = %(attachment; filename="#{file_name}")
37
+
38
+
39
+ return self.response_body = Enumerator.new do |y|
40
+ csv = CSVRb::StreamCSVDeflator.new(y)
41
+ instance_eval lookup_context.find_template(options[:template], options[:prefixes], options[:partial], options.dup.merge(formats: [:csv])).source
42
+ csv.close
43
+ end
44
+ # else
45
+ # disposition = options.delete(:disposition) || 'attachment'
46
+ #
47
+ # send_data render_to_string(options), filename: file_name, type: Mime[:csv], disposition: disposition
48
+ # end
49
+ end
50
+
51
+ # For respond_to default
52
+ begin
53
+ ActionController::Responder
54
+ rescue
55
+ else
56
+ class ActionController::Responder
57
+ def to_csv
58
+ @_action_has_layout = false
59
+ if @default_response
60
+ @default_response.call(options)
61
+ else
62
+ controller.render({csv: controller.action_name}.merge(options))
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,27 @@
1
+ module CSVRb
2
+ class PlainBuilder
3
+ def value
4
+ @value ||= "#{}"
5
+ end
6
+
7
+ def stream(row)
8
+ value << CSV.generate_line(row, force_quotes: true, encoding: 'utf-8')
9
+ end
10
+
11
+ def <<(row)
12
+ stream(row)
13
+ end
14
+
15
+ def close
16
+ to_s
17
+ end
18
+
19
+ def to_str
20
+ to_s
21
+ end
22
+
23
+ def to_s
24
+ value
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CSVRb
4
+ class Railtie < Rails::Railtie
5
+ initializer 'csv_rb.initialization' do
6
+ ActiveSupport.on_load(:action_view) do
7
+ require 'csv_rb/template_handler'
8
+ ActionView::Template.register_template_handler :csvrb, ActionView::Template::Handlers::CSVRbBuilder.new
9
+ end
10
+
11
+ ActiveSupport.on_load(:action_controller) do
12
+ require 'csv_rb/action_controller'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ module CSVRb
2
+ class StreamCSVDeflator
3
+ def initialize(enum)
4
+ @enum = enum
5
+ @deflator = Zlib::Deflate.new
6
+ end
7
+
8
+ def y
9
+ @enum
10
+ end
11
+
12
+ def stream(row)
13
+ v = CSV.generate_line(row, force_quotes: true, encoding: 'utf-8')
14
+ y << @deflator.deflate(v, Zlib::SYNC_FLUSH)
15
+ end
16
+
17
+ def <<(row)
18
+ stream(row)
19
+ end
20
+
21
+ def close
22
+ y << @deflator.flush(Zlib::FINISH)
23
+ end
24
+ end
25
+ end