2

I'm trying to display my image saved in Mongo in the record row with the rails_admin gem.

I have my model saving, and my image saving, and I'm saving the image ID in the model record.

Here's my model:

require 'mongoid/grid_fs'

class Asset
  include Mongoid::Document

  field :data_file_name, type: String  
  field :data_content_type, type: String  
  field :data_file_size, type: Integer
  field :image_id, type: String
end

Here's what I'm trying to do in rails_admin.rb for my Asset model:

list do
  field :id        
  field :data_file_name
  field :data_content_type
  field :data_file_size
  field :image do
    formatted_value do
      grid_fs = Mongoid::GridFs
      bindings[:view].tag(:img, { :src => grid_fs.get(bindings[:object].image_id)})
    end
  end
end

And here's the action responsible for saving the model and image:

register_instance_option :controller do
          proc do
            if request.get? # EDIT
              respond_to do |format|
                format.html { render @action.template_name }
                format.js   { render @action.template_name, layout: false }
              end

            elsif request.put? # UPDATE
              tempFile = params[:picture][:asset].tempfile
              file = File.open(tempFile)
              grid_fs = Mongoid::GridFS
              grid_file = grid_fs.put(file.path)
              Asset.new.tap do |asset|
                asset.data_file_name = params[:picture][:asset].original_filename
                asset.data_content_type = params[:picture][:asset].content_type
                asset.data_file_size = ::ApplicationController.helpers.number_to_human_size(File.size(tempFile))
                asset.image_id = grid_file.id
                asset.save
                binding.pry
              end
            end
          end
        end

The model is saving, and I can see the file saving in fs.files and fs.chunks, but at the moment, I'm just getting the following in the record row: Blank Image

Update:

I've now tried getting the file from mongo (Which seems to work) and then displaying the image by using the file's actual filename.

field :image do
    formatted_value do
        grid_fs = Mongoid::GridFs
        f = grid_fs.get(bindings[:object].image_id)
        bindings[:view].tag(:img, { :src => f.filename})
    end
end

Unfortunately this hasn't changed anything. Trying to open the image in a new tab takes me to the following link: /admin/asset#<Mongoid::GridFs::Fs::File:0x981vj5ry>

Update 2:

Changed field :image_id, type: String to field :image_id, type: BSON::ObjectId

No change in result.

Daniel Lawton
  • 416
  • 3
  • 9
  • 30

2 Answers2

0

If you are saving image data in GridFS, you need to have an endpoint in your application to retrieve that image data from GridFS and serve it to the applications. See this answer for how to serve image data: Rails - How to send an image from a controller

Then, link to this endpoint instead of linking to "f.filename" as you have indicated in the last code snippet.

D. SM
  • 13,584
  • 3
  • 12
  • 21
  • Thanks for taking the time to answer. I'm just wondering - Is there no way of displaying the image without having to save the file locally? Ideally I'd just pull the image data from GridFs with this: `f = grid_fs.get(bindings[:object].image_id) file = File.new(bindings[:object].data_file_name, 'wb') f.each { |chunk| file.write(chunk) }` And then display `file` somehow. – Daniel Lawton Sep 19 '19 at 07:34
  • You do not need to copy the data from GridFS to a local file system to serve it, but you still need an endpoint to retrieve the data from GridFS and then forward it to the browser. – D. SM Sep 19 '19 at 14:37
0

After a lot more research, it looks like you can encode the data returned from grid_fs to base64.

In turn, you can use this to display the image by specifying the source to be data:image/png;base64,+base64Image like so:

field :asset_thumbnail do
    formatted_value do
        grid_fs = Mongoid::GridFs
        f = grid_fs.get(bindings[:object].thumb_image_id)
        b64 = Base64.strict_encode64(f.data)
        bindings[:view].tag(:img, { :src => "data:image/png;base64,"+b64})
    end
end 
Daniel Lawton
  • 416
  • 3
  • 9
  • 30