I am using a ruby gem for gpx parsing and editing. I want to store the edited result in active storage.
The gem has this method for saving
def write(filename, update_time = true)
@time = Time.now if @time.nil? || update_time
@name ||= File.basename(filename)
doc = generate_xml_doc
File.open(filename, 'w+') { |f| f.write(doc.to_xml) }
end
And ActiveStorage has an example for saving
@message.image.attach(io: File.open('/path/to/file'), filename: 'file.pdf')
I could use both of these and it should work but then I am writing the file twice as well as having a an extra unneeded file sitting on the filesystem that needs to be manually removed later.
The ideal situation would be to have the gpx gem directly pass the data to ActiveStorage and let AS be the only one saving the file.
Given write()
seems to be the only way to export/save the data and generate_xml_doc
is a private method, is there any way I can achieve this without forking the gem or monkey patching it?
Looking at the gem documentation, looks like you don't need to use the write
method but instead use to_s
method which should create the xml string which you can then use Tempfile to upload with active storage:
Here's the to_s
method
def to_s(update_time = true)
@time = Time.now if @time.nil? || update_time
doc = generate_xml_doc
doc.to_xml
end
#so assuming you have something like this:
bounds = GPX::Bounds.new(params)
file = Tempfile.new('foo')
file.path # => A unique filename in the OS's temp directory,
# e.g.: "/tmp/foo.24722.0"
# This filename contains 'foo' in its basename.
file.write bounds.to_s
file.rewind
@message.image.attach(io: file.read, filename: 'some_s3_file_name.xml')
file.close
file.unlink # deletes the temp file
UPDATED (thanks @Matthew):
But you may not even need the tempfile, this will probably work
bounds = GPX::Bounds.new(params)
@message.image.attach(io: StringIO.new(bounds.to_s), name: 'some_s3_file_name.xml')