Posted 12 days ago. Visible to the public. Linked content. Auto-destruct in 48 days

Updated: Writing strings as Carrierwave uploads

We do need a custom class after all 😳

Changes

  • When you have string contents (e.g. a generated binary stream, or data from a remote source) that you want to store as a file using Carrierwave, here is a simple solution.
  • While you could write your string to a file and pass that file to Carrierwave, why even bother? You already have your string (or stream).
  • However, a plain StringIO object will not work for Carrierwave's ActiveRecord integration:
  • ```ruby
  • ->> Attachment.create!(file: StringIO.new(string))
  • -# TypeError: no implicit conversion of nil into String
  • +>> Attachment.create!(file: StringIO.new(contents))
  • +TypeError: no implicit conversion of nil into String
  • ```
  • -This is because Carrierwave expects the file upload to respond to `#original_filename`.
  • +This is because Carrierwave expects a filename by default. It makes sense, so here is a simple yet useful helper class:
  • -To do so you can use [`Rack::Test::UploadedFile`](https://www.rubydoc.info/github/brynary/rack-test/Rack/Test/UploadedFile), which adds an `#original_filename` method to any `IO` object:
  • +```ruby
  • +class FileIO < StringIO
  • + def initialize(stream, filename)
  • + super(stream)
  • + @original_filename = filename
  • + end
  • +
  • + attr_reader :original_filename
  • +end
  • +```
  • +
  • +You must simply come up with a filename and can then pass your string or stream directly.
  • +
  • +```
  • +>> Attachment.create!(file: FileIO.new(contents, 'document.pdf'))
  • +=> #<Attachment ...>
  • +```
  • +
  • +When using zeitwerk (Rails 6) you might also need to add an inflection in order to make autoloading work for this file:
  • ```ruby
  • -stream = StringIO.new(string)
  • -file = Rack::Test::UploadedFile.new(stream, original_filename: 'document.pdf')
  • +ActiveSupport::Inflector.inflections(:en) do |inflect|
  • + inflect.acronym 'IO'
  • +end
  • ```
  • -While that class sounds like it would not be available in production environments, it actually is.
  • +Otherwise zeitwerk will complain that the file `file_io.rb` does not define `FileIo`.

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for unsupported versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2).

Owner of this card:

Avatar
Henning Koch
Last edit:
12 days ago
by Henning Koch
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Henning Koch to makandra dev
This website uses short-lived cookies to improve usability.
Accept or learn more