読者です 読者をやめる 読者になる 読者になる

CarrierWaveを利用した画像ファイルのアップロード(5) ファイルのアップロードができない

こんにちは。beaglesoftの真鍋です。

CarrierWaveを利用してファイルのアップロードを行うで、ファイルのアップロードができないケースがあったのでまとめておきます。

事象について

実際のプロジェクトでCarrierWaveを利用してファイルのアップロードを行おうとしたところPOSTパラメーターにはファイル名が設定されているのですが、ActiveRecordの対象となるフィールドにファイル名が設定されない事象に遭遇しました。

原因

生成されるViewを確認したところ、以下のとおりとなっていました。

<form class="form-horizontal" id="edit_service_transaction_1" action="/service_transactions/1" accept-charset="UTF-8" method="post">
    <div class="form-group">
          ...
    <div class="form-group">
      <label class="col-sm-2 control-label" for="attachment_file_afile">Afile</label>
      <div class="col-sm-4">
        <input class="form-control" type="file" name="attachment_file[afile]" id="attachment_file_afile">
      </div>
      <input class="form-control" type="hidden" name="attachment_file[afile_cache]" id="attachment_file_afile_cache">
      ....
    </div>
    <div class="form-group">
      <div class="col-sm-offset-2 col-sm-10">
        <input type="submit" name="commit" value="更新する" class="btn btn-primary">
      </div>
    </div>
</form>

ファイルのアップロードを行うときにはformタグにmultipart設定が必要となるのですが、その設定が出力されていないためうまくファイルのアップロードが行えていませんでした。

multipartについてはenctype='multipart/form-data'ってなんだ? - MUGENUP技術ブログが参考になりました。とてもわかり易かったです。ありがとうございます。

対策

Viewテンプレートにmultipart設定を出力するため以下のとおり修正しました。

/ multipart: trueを追加しました
== form_for(@service_transaction , html: {class: 'form-horizontal', multipart: true} ) do |f|
...

これで出力されるHTMLも下記のとおりとなりファイルが保存できるようになりました。

<form class="form-horizontal" id="edit_service_transaction_1" enctype="multipart/form-data" action="/service_transactions/1" accept-charset="UTF-8" method="post">
    <div class="form-group">
          ...
    <div class="form-group">
      <label class="col-sm-2 control-label" for="attachment_file_afile">Afile</label>
      <div class="col-sm-4">
        <input class="form-control" type="file" name="attachment_file[afile]" id="attachment_file_afile">
      </div>
      <input class="form-control" type="hidden" name="attachment_file[afile_cache]" id="attachment_file_afile_cache">
      ....
    </div>
    <div class="form-group">
      <div class="col-sm-offset-2 col-sm-10">
        <input type="submit" name="commit" value="更新する" class="btn btn-primary">
      </div>
    </div>
</form>

普通にScaffoldして動作するものでも、ちょっと込み入ったことを始めると動かなくなる(自分の理解が足りていないだけ…)ことがあるので、この辺のハマったことはできるだけ公にしていきたいと思います。