LoginSignup
9
7

More than 5 years have passed since last update.

Rails4 の form_for は multipart: true を省略可能

Last updated at Posted at 2014-11-29

5 Uploading Files
http://guides.rubyonrails.org/form_helpers.html#uploading-files

ということらしい。
知らなかったので試してみた。

適当なプロジェクトを作成。

% rails new example --skip-bundle && cd example && bundle install --path=vendor/bundle

環境は以下。

% ./bin/rake about
About your application's environment
Ruby version              2.1.3-p242 (x86_64-linux)
RubyGems version          2.2.2
Rack version              1.5
Rails version             4.1.8
・・・

適当な scaffold を作成。

% bundle exec rails g scaffold post title:string body:text

生成された app/views/posts/_form.html.erb は以下のような内容。

<%= form_for(@post) do |f| %>
  <% if @post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
      <% @post.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

この状態でブラウザからアクセスした際に生成された HTML は以下のようなもの。
当然だけど form タグには enctype="multipart/form-data" は指定されていない。

<!DOCTYPE html>
<html>
<head>
  <title>Example</title>
  <link data-turbolinks-track="true" href="/assets/posts.css?body=1" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/assets/scaffolds.css?body=1" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/assets/application.css?body=1" media="all" rel="stylesheet" />
  <script data-turbolinks-track="true" src="/assets/jquery.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/jquery_ujs.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/turbolinks.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/posts.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/application.js?body=1"></script>
  <meta content="authenticity_token" name="csrf-param" />
<meta content="wvtYCGLda3V5pS0q0kuXG4rqHz4kVsCAlQW8BFZI91M=" name="csrf-token" />
</head>
<body>

<h1>New post</h1>

<form accept-charset="UTF-8" action="/posts" class="new_post" id="new_post" method="post"><div style="display:none"><input name="utf8" type="hidden" value="&#x2713;" /><input name="authenticity_token" type="hidden" value="wvtYCGLda3V5pS0q0kuXG4rqHz4kVsCAlQW8BFZI91M=" /></div>

  <div class="field">
    <label for="post_title">Title</label><br>
    <input id="post_title" name="post[title]" type="text" />
  </div>
  <div class="field">
    <label for="post_body">Body</label><br>
    <textarea id="post_body" name="post[body]">
</textarea>
  </div>
  <div class="actions">
    <input name="commit" type="submit" value="Create Post" />
  </div>
</form>

<a href="/posts">Back</a>


</body>
</html>

app/views/posts/_form.html.erb に以下のように file_field を追加してみる。

  <div class="field">
    <%= f.label :image %><br>
    <%= f.file_field :image %>
  </div>

この状態で再度ブラウザからアクセスして生成された HTML は以下。

<!DOCTYPE html>
<html>
<head>
  <title>Example</title>
  <link data-turbolinks-track="true" href="/assets/posts.css?body=1" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/assets/scaffolds.css?body=1" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/assets/application.css?body=1" media="all" rel="stylesheet" />
  <script data-turbolinks-track="true" src="/assets/jquery.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/jquery_ujs.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/turbolinks.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/posts.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/application.js?body=1"></script>
  <meta content="authenticity_token" name="csrf-param" />
<meta content="wvtYCGLda3V5pS0q0kuXG4rqHz4kVsCAlQW8BFZI91M=" name="csrf-token" />
</head>
<body>

<h1>New post</h1>

<form accept-charset="UTF-8" action="/posts" class="new_post" enctype="multipart/form-data" id="new_post" method="post"><div style="display:none"><input name="utf8" type="hidden" value="&#x2713;" /><input name="authenticity_token" type="hidden" value="wvtYCGLda3V5pS0q0kuXG4rqHz4kVsCAlQW8BFZI91M=" /></div>

  <div class="field">
    <label for="post_title">Title</label><br>
    <input id="post_title" name="post[title]" type="text" />
  </div>
  <div class="field">
    <label for="post_body">Body</label><br>
    <textarea id="post_body" name="post[body]">
</textarea>
  </div>
  <div class="field">
    <label for="post_image">Image</label><br>
    <input id="post_image" name="post[image]" type="file" />
  </div>
  <div class="actions">
    <input name="commit" type="submit" value="Create Post" />
  </div>
</form>

<a href="/posts">Back</a>


</body>
</html>

ちゃんと form タグに enctype="multipart/form-data" が指定されている。

いつからこういう挙動になったのかまでは確認していないが、少なくとも Rails 4.1 では form_for の場合はブロック内で file_field を使っている場合、いちいち multipart: true を指定しなくてもいいみたいだ。

2016.06.20 追記:

コメント欄で教えて頂いたが、3.1 からこの挙動だった模様。

参考

form_tagでファイルアップロード時はmultipart:trueを省略しない[Rails4] - source
http://source.hatenadiary.jp/entry/2014/03/21/143914

9
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7