Rails 3.2 で CarrierWave を使う時に public 以下にファイルを置きたくない場合
CarrierWave は便利なプラグインですが、デフォルト設定のまま Rails で使うと public 以下の誰でもアクセス可能なディレクトリにファイルを書き込んでしまいます。これでは困る場合は config/application.rb で以下のようにデフォルトのアップロード先を指定します。
module Hoge class Application < Rails::Application # 略 CarrierWave.configure do |config| config.root = Rails.root end end end
これで書き込みは public 以下ではなく Rails.root 直下をベースに行われる…のですが、肝心のファイルの読み出しの方がうまくいきません。自由にアクセスできない位置にファイルを置きたかったので成功と言えば成功ですが、適切なユーザがファイルを見られるように設定してあげる必要があります。これを実現するために、ファイルの読み出し用のコントローラを作成します。名前は attachments_controller.rb とします。
rails g controller attachments
コントローラを作ったら、ファイル表示用のメソッドを作成します。File.binread は Ruby 1.9 系のメソッドなので Ruby 1.8 系を使う時は適宜書き換えてください。
class AttachmentsController < ApplicationController def show full_path = "#{Rails.root}" + params[:path] image = File.binread(full_path) send_data image, :disposition => 'inline' end end
続いて config/route.rb にルーティングを記述。
Hoge::Application.routes.draw do get "attachments/show" # 中略 end
最後に、ビューの表記を書き換えます。元のビューではこのように記述しているとします。
<%= image_tag hoge.image_url %>
これを以下のように変更します。
<%= image_tag(url_for(:controller => 'attachments', :action => 'show', :path => hoge.image_url)) %>
後は、先ほど作った attachments_controller の中で適宜認証をかけてあげれば、必要なユーザのみが目的の画像を見られるようになります。
class AttachmentsController < ApplicationController def show render :text => "Not Allowed" unless authenticate # 適当に認証したとする full_path = "#{Rails.root}" + params[:path] image = File.binread(full_path) send_data image, :disposition => 'inline' end end