code4j
code4j

Reputation: 4646

file paths will not update after file upload in rails production environment

I have a rails application which will upload image with the name as same as the book id to assets/books_icon when the user creates a book.

upload_icon(params[:book][:image_upload])

# upload_image when create/update book
    def upload_icon(uploaded_io)
       photo_directory = "app/assets/images/"

       # only when user upload the iphoto
       if uploaded_io.present?

         # upload to the exact location with category_id
         extension = File.extname(uploaded_io.original_filename)
         photo_location = 'books_image/'+ @book.id.to_s + extension

         # open in binary mode
         photo_full_location = photo_directory + photo_location
         File.open(photo_full_location, 'wb') do |file|
           file.write(uploaded_io.read)
         end

         # only have to state which is the directory, 
         # image_tag will use assets piepline which will add 'assets/images/' as prefix in src 
         @book.update_attribute(:image_url, photo_location)
       end
     end

It works in the development mode.Then, I deployed the rails application with passenger on mac Apache2 server with mysql as the database and I changed config.assets.compile = true in the development configuration file.

In the production mode, I can create the new book and I can upload the image to assets/books_icon. However, the file path for the image which I just upload will not update.

For example, I create a new book with id 2, and there is 2.jpg in assets/books_icon. But the rails application will told me http://localhost/assets/images/books_icon/2.jpg is missing.

However, when I restart the apache server, I can view the picture at http://localhost/assets/images/books_icon/2.jpg

Is there any solutions to solve this type of caching problem??

Upvotes: 0

Views: 1123

Answers (1)

Tom Harrison
Tom Harrison

Reputation: 14028

In this context, an uploaded image isn't really considered an "asset" -- think of it as data that you happen to be storing somewhere else. (An image asset might be a logo, or background image, etc.). Rails' asset pipeline does some pretty tricky stuff in order to resolve a simple file path to an actual resource (e.g. image) when it's an asset.

By default, Rails makes the app/public folder the document root, and thus a place that you could upload images to -- perhaps in a subdirectory called "upload/img" in which case you could reference it with the path /upload/img/mybook.jpg.

This approach tends to be fragile, however because the image is really directly associated with data in your database, but located on the filesystem of a server. It starts falling apart when you move from development to stagings or production servers.

One approach I would not recommend is to upload the image and store it as a blob type in your database. Another I would recommend is to have another "central" server that you can upload images to that acts as an extension to your database. Many people use Amazon AWS "S3" service for this kind of thing. Take a look at the CarrierWave gem which does an excellent job of making all of this really easy, flexible, and powerful.

Upvotes: 2

Related Questions