プラグインを使わずにnested attributesでファイルアップロードを扱う方法のサンプルです。悩むのはinputのnameの指定方法と、Strong Parametersの書き方。
例はItem has many Attachment の構造
% bin/rails g scaffold item name
% bin/rails g model attachment filename item_id:integer
app/views/items/_form.html.erb
<%= form_for(@item, :html => {:multipart => true}) do |f| %>
<!--途中省略-->
<%= f.file_field "attachment", :multiple => true, name: "item[attachments_attributes][][file]" %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
app/controllers/items_controller.rb
def item_params
params.require(:item).permit(:name,
:attachments_attributes => [:file])
end
app/models/item.rb
class Item < ActiveRecord::Base
has_many :attachments
accepts_nested_attributes_for :attachments
end
app/models/attachment.rb
class Attachment < ActiveRecord::Base
belongs_to :item
def file=(file)
self.filename = file.original_filename
# ここではサンプルとしてファイル名を保存している
end
end
HTML5非対応(input type="file" multiple="multiple"に非対応)のブラウザ相手の場合、フォームとコントローラを少し変更
app/views/items/_form.html.erb
<%= form_for(@item, :html => {:multipart => true}) do |f| %>
<!--途中省略-->
<%= f.fields_for :attachments do |attachment_form| %>
<div class="field">
<%= attachment_form.file_field :file %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
app/controllers/items_controller.rb
def new
@item = Item.new
5.times { @item.attachments.build }
end
# (途中省略)
def item_params
params.require(:item).permit(:name,
:attachments_attributes => [:file])
end