How do you seed images using Shrine
Asked Answered
R

2

6

I can't seed my images using shrine, unlike carrierwave the below code doesn't work.

Profile.create! id: 2,
                user_id: 2, 
                brand: "The Revengers", 
                location: "Azgaurd", 
                phone_number: "send a raven",
                image_data: File.open(Rails.root+"app/assets/images/seed/thor.png")

i've also tried

image_data: ImageUploader.new(:store).upload(File.open(Rails.root+"app/assets/images/seed/thor.png"))

but it returns

JSON::ParserError in Profiles#show
743: unexpected token at '#<ImageUploader::UploadedFile:0x007fd8bc3142e0>'

Is there a shrine way? I can't seem to find it anywhere.

shrine.rb

require "cloudinary"
require "shrine/storage/cloudinary"


Cloudinary.config(
  cloud_name: ENV['CLOUD_NAME'],
  api_key:ENV['API_KEY'],
  api_secret:ENV['API_SECRET'],
)

Shrine.storages = {
  cache: Shrine::Storage::Cloudinary.new(prefix: "cache"), # for direct 
uploads
  store: Shrine::Storage::Cloudinary.new(prefix: "store"),
}

profile.rb

class Profile < ApplicationRecord
  include ImageUploader[:image]
  belongs_to :user
  has_and_belongs_to_many :genres
  scoped_search on: [:brand]
end

image_uploader.rb

class ImageUploader < Shrine
end
Robespierre answered 13/11, 2017 at 9:41 Comment(4)
Please share Profile class definition along with Shrine initializer and the ImageUploader.rbCrosspollinate
Okay, I've added the extra information above.Robespierre
do you get any error messages when you run the command?Crosspollinate
Not when i run db:seed, but when i go to the profile it wont load the image. 743: unexpected token at '#<File:0x007f83204b7800>'Robespierre
C
13

Using Shrine, the attachment attribute (e.g. image_data) on the model (e.g. Profile) is a text column in the database (you can define it as json or jsonb too). Now it should be clear that this column cannot accept a File object (which you are trying to do).

First you need to use an uploader (e.g. ImageUploader) to upload the target file in one of your configured Shrine storages (e.g. :cache or :store):

uploader = ImageUploader.new(:store)
file = File.new(Rails.root.join('app/assets/images/seed/thor.png'))
uploaded_file = uploader.upload(file)

Here the main method of the uploader is #upload, which takes an IO-like object on the input, and returns a representation of the uploaded file (ImageUploader::UploadedFile) on the output.

At this point, you have the uploaded file in hand. Now the model (Profile) will only need the json representation of the uploaded file in its attachment attribute column (image_data) like so:

Profile.create! id: 2,
                user_id: 2, 
                brand: "The Revengers", 
                location: "Azgaurd", 
                phone_number: "send a raven",
                image_data: uploaded_file.to_json
Crosspollinate answered 15/11, 2017 at 7:58 Comment(1)
Works! Beautiful!Robespierre
M
0

Updating this answer to work with the latest version of Shrine (3.4.0).

models/profile.rb

class Profile < ApplicationRecord
  #  image_data  :jsonb (in the database)

  # add an `image` virtual attribute managed by Shrine
  include ImageUploader::Attachment.new(:image)
end

In a rails console:

file = URI.open("https://picsum.photos/200/300")
profile = Profile.first
profile.image = file
profile.save

With that, the uploader uploads and processes the file as if it were uploaded in a form.

Mackoff answered 27/6, 2022 at 0:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.