如何通过ActiveStorage上传图片
class Medium < ActiveRecord::Base has_one_attached :image end Ruby
Attach remote file
with ‘require open-uri’
require 'open-uri' file = open('https://meme.eq8.eu/noidea.jpg') medium = Medium.last medium.image.attach(io: file, filename: 'some-image.jpg') # or medium.image.attach(io: file, filename: 'some-image.jpg', content_type: 'image/jpg') Ruby
Or without require
require 'uri' file = URI.open('https://meme.eq8.eu/noidea.jpg') medium = Medium.last medium.image.attach(io: file, filename: 'some-image.jpg') # or medium.image.attach(io: file, filename: 'some-image.jpg', content_type: 'image/jpg') Ruby
If you want to get filename from url
require 'uri' uri = URI.parse('https://meme.eq8.eu/noidea.jpg') filename = File.basename(uri.path) Ruby
So put all that together
require 'uri' url = 'https://meme.eq8.eu/noidea.jpg' filename = File.basename(URI.parse(url).path) file = URI.open('https://meme.eq8.eu/noidea.jpg') medium = Medium.last medium.image.attach(io: file, filename: filename, content_type: 'image/jpg') Ruby
to get the mimetype you can use Rack::Mime.mime_type('.jpg') from the ".#{url.split('.').last}
Attach local file
medium = Medium.last medium.image.attach(io: File.open("/tmp/some-image.jpg"), filename: "some-image.jpg", content_type: "image/jpg") Ruby
If you want to get filename and mime_type from the file:
filename = File.basename("/tmp/some-image.jpg") # => some-image.jpg extension = File.extname("/tmp/some-image.jpg") # => .jpg mime_type = Rack::Mime.mime_type(a) #=> "image/jpeg" Ruby
or with Pathname
pathname = Pathname.new('/tmp/some-image.jpg') pathname.basename.to_s # => some-image.jpg pathname.extname # => .jpg Rack::Mime.mime_type(pathname.extname) # => "image/jpeg" Ruby
all together:
medium = Medium.last pathname = Pathname.new('/tmp/some-image.jpg') medium.image.attach(io: File.open(pathnname), filename: pathname.basename.to_s, content_type: Rack::Mime.mime_type(pathname.extname)) Ruby
Attach local file as a uploaded medium
Sometimes you want the file in a console to appear as it was uploaded via a Controller.
For example if you are writing a db:seed where you attach local file you may want to reuse bit of functionality that uses bit of controller logic:
medium.image = params.permit(:image) Ruby
so Here you wont be able to do medium.image.attach(io: File.open('...'), content_type: '...')
Solution:
# app/controller/media_controller.rb # ... def create # ... Medium.upload_via_controller(params[:image]) # ... end end Ruby# app/models/medium.rb class Medium < ActiveRecord::Base has_one_attached :image def self.upload_via_controller(file_from_controller) medium = Medium.new medium.image = file_from_controller # ...some other logic like set default order medium.save end end Ruby# lib/tasks/create_dummy_data.rake module MyRakeHelper extend ActionDispatch::TestProcess def self.create_dummy_medium img = Rails.root.join('db/data/dummy-work.jpg') img = dummy_file_uplod(img.to_s, 'image/jpg') ## ...or: # img = dummy_file_uplod(img.to_s, Rack::Mime.mime_type(img.extname)) Medium.upload_via_controller(img) # we want to reuse existing logic in our raketask end def self.dummy_file_uplod(file_fixture_path, type) Rack::Test::UploadedFile.new(file_fixture_path, type) end end task create_dummy_images: :environment do MyRakeHelper.create_dummy_medium end Ruby
Note: For tests you could use:
# spec/my_spec.rb # require 'action_dispatch/testing/test_proces' # may be needed module UploadHelper extend ActionDispatch::TestProcess::FixtureFile # rails 6 # extend ActionDispatch::TestProcess # order Rails like rails 3.2 def upload(img) fixture_file_upload(img.to_s, Rack::Mime.mime_type(img.extname)) end end it do img = UploadHelper.upload( Rails.root.join('spec/fixtures/myimg.jpg) ) medium = Medium.create(image: img) # ... end Ruby
- https://api.rubyonrails.org/classes/ActionDispatch/TestProcess/FixtureFile.html
- https://github.com/rails/rails/blob/83217025a171593547d1268651b446d3533e2019/actionpack/lib/action_dispatch/testing/test_process.rb#L19
Sources
- https://edgeguides.rubyonrails.org/active_storage_overview.html#attaching-file-io-objects
- https://blog.eq8.eu/til/factory-bot-trait-for-active-storange-has_attached.html
Related articles
- Factory Bot trait for attaching ActiveStorange has_attached
- How to store image width & height in Rails ActiveStorage
- Rails ActiveStorage - crop and resize image variant
- change host in active storage
阅读量: 681
发布于:
修改于:
发布于:
修改于: