同じにやっても動かない

書いてある通りやっているのに動かないのです

ドラッグアンドドロップで写真をアップロードしてDragonflyで扱いたい on rails

facebooktwitterのように、ブラウザにドラッグアンドドロップすると自動でアップロードしてプレビュー表示というのをやりたかったので、色々と試してみました。

ドラッグアンドドロップでアップロード

この動作自体はjquery-html5-uploaderというプラグインを使ったら、えらく簡単にできました。

jquery-html5-uploaderのページに書いてある通り、プラグインをロードしてドロップ先のdiv要素とinput要素を用意するだけです。

アップロード先には、Dragonflyのphotoモデルを扱っているphotosコントローラを指定します。
こんな感じです。

$("#image-upload-area, #new_photo").html5Uploader({
    name: "dd_file",
    postUrl: "<%= photos_url %>"
});

アップロードされたファイルをDragonflyで扱う

ここではまりました。
photoモデルに紐付いたフォームでアップロードされるわけではないので、いつものように

@photo = Photo.new(params[:dd_file])
# dd_fileは上記javascriptのnameに指定した名前

とやっても、インスタンスを生成できません。


Dragonflyのドキュメントを読んでみると、tempfileオブジェクトからインスタンスを生成できると書いてあります。
最終的には下記の手順で無事写真を登録することができました。

  def create
    if ( params[:dd_file] )
      # Dragonflyアプリケーションを生成
      app = Dragonfly[:photo] 
      # params[:dd_file].tempfileでtempfileオブジェクトを取り出し、画像ファイルを生成
      image_file = app.create(params[:dd_file].tempfile).to_file(params[:dd_file].original_filename) 
      # photoモデルインスタンス生成
      @photo = Photo.new
      # photo modelで定義したアクセッサ(photo_image)に画像ファイルをコピー
      @photo.photo_image = image_file
    end
    
    respond_to do |format|
      if @photo.save
        format.js
        format.html { redirect_to @photo, notice: 'Photo was successfully created.' }
        format.json { render json: @photo, status: :created, location: @photo }
      else
        format.html { render action: "new" }
        format.json { render json: @photo.errors, status: :unprocessable_entity }
      end
    end
  end


できてみると簡単なのですが、プレビュー動作も含めるとなんだかんだで2日もかかってしまいました。

[追記] CSRFトークンの追加

うまくいったと思ってよろこんでいたのですが、こんなログが出ていました。

WARNING: Can't verify CSRF token authenticity

jquery-html5-uploader経由だと、CSRFトークンが付かないので怒られているようです。
というわけで、jquery-thml5-uploader.jsに下記2行を追加することにしました。

var csrf_token = $("meta[name=csrf-token]").attr("content");
xmlHttpRequest.setRequestHeader("X-CSRF-Token", csrf_token);

追加した場所は、ファイルの後方で xmlHttpRequest.open("POST", settings.postUrl, true); の直後です。