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="✓" /><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="✓" /><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