Ognjen Regoje bio photo

Ognjen Regoje
But you can call me Oggy

I make things that run on the web (mostly).
More ABOUT me and my PROJECTS.

me@ognjen.io LinkedIn

Restricting uploaded files to logged in users with carrierwave

#carrierwave #rails #ruby #technical

I’ve had this in my notes for a long time. In order to not upload files to your public/ folder, which is the default for carrier wave, it’s really simple. Just need to change a couple of things.

In your uploader, in this example documents_uploader, change the path where the files are stored. You can even do the least work and change public to uploads. (If you do that, make sure to exclude uploads from git and to link uploads when your application is deployed.)

# app/uploaders/documents_uploader.rb
  def store_dir
    # before:
    # File.join(Rails.root, "public", "#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}")

    # After:
    File.join(Rails.root, "uploads", "#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}")

Second, you need to create a controller and call it something like FileController or UploadedFilesController. All that it needs to do is return the file.

# app/controllers/files_controller.rb
class FilesController < ApplicationController
  before_action :authenticate_user!
  def show
    File.open(params[:id] + "." + params[:format], 'rb') do |f|
      send_data f.read, :type => "image/#{params[:format]}", :disposition => "inline"

and in your routes

# config/routes.rb
resources :files, only: [:show]

then you can use it as follows in your views:

<%= image_tag file_url(@post.featured_photo.file.file) if @post.featured_photo?%>

A caveat regarding mime types and formats: this is the absolute simplest and quickest way of handling authentication for files but you might have issues because the show action in the files controller just blindly assumes that the type is the format and that the format is after the dot, etc, etc. There are more robust ways to handle the File.open part but for my purpose they were not needed.