I am new to rails so sorry if this is easy. I am wondering the best w开发者_C百科ay to upload pictures and display them in Ruby on Rails. I have a blog and would like to have the option of attaching a picture when creating a post.
Paperclip is quite awesome. There's an excellent RailsCast about it - http://railscasts.com/episodes/134-paperclip
CarrierWave is a newer gem than Paperclip, and it looks a lot more flexible. There's also a Railscast about it: http://railscasts.com/episodes/253-carrierwave-file-uploads
Assuming you don't need fancy features, don't wish to add a dependency and want to store the image as a BLOB in your DB, you can do something like:
Model:
class Image < ActiveRecord::Base
def img=(input_data)
self.filename = input_data.original_filename
self.filetype = input_data.content_type.chomp
self.img = input_data.read
end
end
Controller:
class ImagesController < ApplicationController
def display_img
@img = Image.find(params[:id])
send_data(@img.img, :type => @img.filetype, :filename => @img.filename,
:disposition => 'inline')
end
end
Here's a link to a more complete tutorial.
Many recommend to use Carrierwave
and I am not an exception but I wanted to point one thing out. On many sites written with RoR (it's obviously not only RoR issue though) I notice that the request that's sending the picture can be pending for like 2-3 secs and often even more which ties up the application instance (which is probably not that terrible if you're using threads or don't care much about performance but it definitely is if you're using unicorn). So I'll explain how to avoid that using carrierwave:
1) Pick some background worker for your app (I usually go with Sidekiq)
2) Add carrierwave_backgrounder
to your Gemfile and configure it to work with your background worker and carrierwave (everything in its readme)
I usually have control over my directories so I go with store_in_background
option of carrierwave_backgrounder
which processes and stores the picture in the file system or S3 or whatever you're using
3) Now, when you update the picture, its processing and storing goes to background , which frees your application instance but it takes a while, in most cases more than 1 second, and you need to return some response to the user
4) The easiest way to provide user with some response is to return javascript in which you change the old picture to a gif with a spinner or something like that and set javascript SetInterval
function that checks if the picture has been processed (carrierwave_background
provides a function that can change the boolean column of your model to true when it's done processing) sending AJAX
request every 2 seconds or whatever you prefer and change the picture when it's been processed.
Now you have an untied application instance and a fine user experience at the same time.
PS I am new to rails and web development per se so this guide may have some caveats that I've missed
Hope it'll help somebody.
Oh, and by the way, there's this new gem called refile
, it's amazing and can be a really good option in some cases.
Many people recommend PaperClip. Perhaps you want to try using that first.
CarrierWave is probably the best solution for picture uploading in Rails. The following post describes a solution for image uploading using CarrierWave while image transformations are done seamlessly in the cloud. Uploaded images are stored in the cloud and delivered through a CDN. No need to install RMagick, MiniMagick and ImageMagick. http://cloudinary.com/blog/ruby_on_rails_image_uploads_with_carrierwave_and_cloudinary
attachment_fu (http://github.com/technoweenie/attachment_fu
) is another option although I personally would recommend paperclip. It doesn't require Rmagick which is a big plus, and it supports some cool features like uploads to S3 with minor configuration.
Updated at August 2019
For anyone checking this question recently, Rails 5.2+ now has ActiveStorage by default & I highly recommend checking it out.
Since it is part of the core Rails 5.2+ now, it is very well integrated & has excellent capabilities out of the box (still all other well-known gems like Carrierwave, Shrine, paperclip,... are great but this one offers very good features that we can consider for any new Rails project)
Paperclip team deprecated the gem in favor of the Rails ActiveStorage.
Here is the github page for the ActiveStorage & plenty of resources are available everywhere
Important note
Please note that some advanced features are not available in ActiveStorage, but if your use case is simple, it can be one of the easiest uploading gems to install & integrate with 3rd party cloud storage (s3, digital ocean spaces, ....)
One of the main drawbacks for example, is that you can't define paths for your uploads in ActiveStorage, there is a hack to do that, so that each environment will upload to a different path (but still that was a big annoyance for me)
If your upload needs more flexibility & advanced features, I recommend checking out Shrine
Shrine comparison with other gems, as per their official page
精彩评论