railsのプロジェクトで複数ファイルを一度にアップロードしたい時があります!
そんなときにはこんな感じでやればうまくいく。という一例をまとめておきます。
①まずアップロードに使うviewを編集します
といっても、
:multiple => true
をつければOK!
_form.html.slim
= form_for @photo do |f|
- if @photo.errors.any?
#error_explanation
h2 = "#{pluralize(@photo.errors.count, "error")} prohibited this photo from being saved:"
ul
- @photo.errors.full_messages.each do |message|
li = message
.field.mb_20
= f.label :content
= f.file_field :content, :multiple => true
.field.mb_20
= f.text_field :title
.actions = f.submit
ちなみ今回は、:title
も一緒にアップロードすることにします
②次にControllerのStrong Parametersをmultipleに対応させます
hashっぽく{}でくくって、配列が入る事を指定します
controller.rb
def photo_params
params.require(:photo).permit( :title, {content: []})
end
これで、photo_paramsでcontentの配列までとれるはずです。
③次にModelにメソッドを用意します
photo.rb
def self.create_photos_by(photo_params)
/* そもそも一枚も上がってきてない時のためのvalidate */
return false if photo_params[:content].nil?
/* 途中でエラった時にRollbackするようにTransaction */
Photo.transaction do
/* アップロードされた画像を一枚ずつ処理 */
photo_params[:content].each do |photo|
new_photo = Photo.new(title: photo_params[:title], content: photo)
return false unless new_photo.save!
end
end
true
end
④じゃあ、作ったModelメソッドにparameterをぶん投げます
controller.rb
def create
@photo = Photo.new(photo_params) /* ここはformatの部分で使うインスタンス変数用 */
respond_to do |format|
if Photo.create_photos_by(photo_params)
format.html { redirect_to photos_path, notice: 'Photo was successfully created.' }
format.json { render :show, status: :created, location: @photo }
else
format.html { render :new }
format.json { render json: @photo.errors, status: :unprocessable_entity }
end
end
end
これで完成!