###知りたいこと
以下の3つがわからず開発が止まっています
- ActionDispatch::Http::UploadedFileを表示する方法
- ActionDispatch::Http::UploadedFileを保存する方法
- ビューを隔ててもzipファイルを保存する方法
###環境
rails 4.2.6
jquery-ui-rails 6.0.1
mysql Ver 8.0.11 for osx10.13 on x86_64 (Homebrew)
productsテーブルのカラムは以下です。
t.integer "area_id", limit: 4
t.string "building_name", limit: 255
t.string "number", limit: 255
t.string "station", limit: 255
t.string "address", limit: 255
t.text "zip", limit: 65535
t.text "products_image1", limit: 65535
※ products_image1 ~ 30まであります。
###実装手順
- pre_sort.html.erbで6つのカラムに入力し、その後ドラッグ&ドロップ(dropzone.js)でinputタグ(name=products_images[])に画像ファイルを複数入れて「作成」を押します。
2. sort.html.erbでproducts_imagesを一覧表示させて、jQuery-UIのSortableで並び替えて「作成」を押し、保存します。
###問題点
-
sort.html.erbに遷移した時点で、products_imagesにはActionDispatch::Http::UploadedFileオブジェクトの配列が入っていましたが、個々をそのままimage_tagやdivタグのbackground-imageにいれても画像が表示されません。
-
sort.html.erbでバリデーションを外して送信すると、products_image1
30とzipに値が入っていますが、何も表示されません。products_image130とzip両方共、バリデーションを記述するとレコード作成は弾かれます。
###実装コード
ルーティング
ruby
1#routes.rb 2namespace :manage do 3 resources :products do 4 member do 5 get 'pre_sort' 6 post 'sort' 7 post 'create_sorted' 8 end 9 end 10end
コントローラ
ruby
1#manage/products_controller.rb 2 def pre_sort 3 @product = Product.new 4 @areas = Area.all 5 end 6 7 def sort 8 @product = Product.new(product_params) 9 @products_images = params[:products_images] 10 end 11 12 def create_sorted 13 @product = Product.new(product_params) 14 15 @product.building_name = ActiveSupport::Multibyte::Unicode.normalize(@product.building_name, :c) 16 @product.address = ActiveSupport::Multibyte::Unicode.normalize(@product.address, :c) 17 18 num = 1 19 params[:products_images].each do |img| 20 @product.send("products_image#{num}=", img) 21 num += 1 22 end 23 24 respond_to do |format| 25 if @product.save 26 format.html { redirect_to [:manage, @product], notice: "#{@product.building_name}を作成しました。" } 27 format.json { render :show, status: :created, location: @product } 28 else 29 format.html { render :pre_sort } 30 format.json { render json: @product.errors, status: :unprocessable_entity } 31 end 32 end 33 end 34
ビュー①(pre_sort.html.erb)
ruby
1#manage/products/pre_sort.html.erb 2 3<%= form_for([:manage,@product], url: { action: "sort"}, html: { multipart: true }) do |f| %> 4 <div class="input manage-product-create-form"> 5 <p class="row"><%= f.label :area_id, class: "label" %><%= f.select :area_id, @areas.map{ |t| [t.name, t.id] }, include_blank: true %></p> 6 <p class="row"><%= f.label :building_name, class: "label" %><%= f.text_field :building_name %></p> 7 <p class="row"><%= f.label :number, class: "label" %><%= f.text_field :number %></p> 8 <p class="row"><%= f.label :floor, class: "label" %><%= f.select :floor, Request::FLOOR, include_blank: true %></p> 9 <p class="row"><%= f.label :station, class: "label" %><%= f.text_field :station %></p> 10 <p class="row"><%= f.label :address, class: "label" %><%= f.text_field :address %></p> 11 <p class="row" id="js-selectFile"> 12 <%= f.label "ダウンロードZIP", class: "label" %> 13 <%= f.file_field :zip, id: "js-upload" %> 14 <%= f.hidden_field :zip_cache, id: "js-upload-cache" %> 15 <button class="original-btn">ZIPファイルを選択</button> 16 <span class="icon">未選択</span> 17 </p> 18 <input type='file' name='products_images[]' multiple=true class='uploadFile' id="fileInput" /> 19 <div id="drop_zone"><i class="fa fa-picture-o" aria-hidden="true"></i> 物件写真をドラッグ&ドロップしてください</div> 20 <div id="preview"></div> 21 </div> 22 <div class="actions"> 23 <%= button_tag type: 'submit', class: "btn-edit" do %> 24 <i class="fa fa-pencil" aria-hidden="true"></i> 作成 25 <% end %> 26 </div> 27<% end %>
ビュー②(sort.html.erb)
ruby
1#manage/products/sort.html.erb 2<div class="input manage-product-create-form"> 3 <p class="row"><label class="label">エリア</label><%= @product.area_id %></p> 4 <p class="row"><label class="label">物件名</label><%= @product.building_name %></p> 5 <p class="row"><label class="label">号室</label><%= @product.number %></p> 6 <p class="row"><label class="label">間取り</label><%= @product.floor %></p> 7 <p class="row"><label class="label">駅名</label><%= @product.station %></p> 8 <p class="row"><label class="label">住所</label><%= @product.address %></p> 9 <p class="row"><label class="label">DL用zip</label><%= @product.zip.url %></p> 10 11 <% (@products_images).each do |img| %> 12 <%= image_tag img, size: '100x100' %> 13 <% end %> 14 15 <%= form_for([:manage,@product], url: { action: "create_sorted"}, html: { multipart: true }) do |f| %> 16 <div class="file-upload-area"> 17 <div class="sort-box-container sortable"> 18 <% (@products_images).each do |img| %> 19 <div class="sort-box"> 20 <input type="text" class="form-control" readonly="" /> 21 <div style='border: dashed 1px #ccc;'> 22 <%= hidden_field_tag 'products_images[]', value: img, class: 'uploadFile', style: 'width: 90px; font-size: 16px;' %> 23 <div class="imagePreview item" style='padding: 0; background-image: <%= img %>'></div> 24 </div> 25 </div> 26 <% end %> 27 </div> 28 </div> 29 <%= f.hidden_field :area_id, value: @product.area_id %> 30 <%= f.hidden_field :building_name, value: @product.building_name %> 31 <%= f.hidden_field :number, value: @product.number %> 32 <%= f.hidden_field :floor, value: @product.floor %> 33 <%= f.hidden_field :station, value: @product.station %> 34 <%= f.hidden_field :address, value: @product.address %> 35 <%= f.hidden_field :zip, value: @product.zip_url %> 36 </div> 37 38 <div class="actions"> 39 <%= button_tag type: 'submit', class: "btn-edit" do %> 40 <i class="fa fa-pencil" aria-hidden="true"></i> 作成 41 <% end %> 42 </div> 43<% end %>
Sortable.js
jquery
1$(function() { 2 $('.sortable').sortable({ 3 update: function(e, ui) { 4 $('.sortable').sortable('toArray'); 5 } 6 }); 7 $(document).on('change', '.uploadFile', function() { 8 var input = $(this); 9 10 label = input.val().replace(/\_/g, '').replace(/.[^/.].+$/, "").slice( -12 ); 11 input.parent('div').prev('.form-control').val(label); 12 13 var files = !!this.files ? this.files : []; 14 if (!files.length || !window.FileReader) return; 15 if (/^image/.test( files[0].type)){ 16 var reader = new FileReader(); 17 reader.readAsDataURL(files[0]); 18 reader.onloadend = function(){ 19 input.next('.imagePreview').css("background-image", "url("+this.result+")"); 20 } 21 } 22 }); 23});
Dropzone.js
jquery
1$(function(){ 2 var formData = new FormData(); 3 var dropZone = document.getElementById("drop_zone"); 4 var fileInput = document.getElementById("fileInput"); 5 6 if (!($('#drop_zone').length)){ 7 return false; 8 } 9 10 dropZone.addEventListener("dragover", function(e) { 11 e.stopPropagation(); 12 e.preventDefault(); 13 14 this.style.background = "#87cefa"; 15 }, false); 16 17 dropZone.addEventListener("dragleave", function(e) { 18 e.stopPropagation(); 19 e.preventDefault(); 20 21 this.style.background = "#ffffff"; 22 }, false); 23 24 dropZone.addEventListener("drop", function(e) { 25 e.stopPropagation(); 26 e.preventDefault(); 27 28 this.style.background = "#ffffff"; 29 30 var files = e.dataTransfer.files; 31 32 fileInput.files = files; 33 for (var i = 0; i < files.length; i++) { 34 (function() { 35 var fr = new FileReader(); 36 fr.onload = function() { 37 var div = document.createElement('div'); 38 39 var img = document.createElement('img'); 40 img.setAttribute('src', fr.result); 41 div.appendChild(img); 42 43 var preview = document.getElementById("preview"); 44 preview.appendChild(div); 45 }; 46 fr.readAsDataURL(files[i]); 47 })(); 48 49 formData.append("file", files[i]); 50 } 51 }, false); 52 53}); 54
長くなってしまい申し訳ありません。
ご指摘いただけることがあれば何卒よろしくお願いいたします。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/02/15 05:53
退会済みユーザー
2019/02/15 05:57
2019/02/15 06:10
退会済みユーザー
2019/02/15 06:32 編集
退会済みユーザー
2019/02/15 06:35 編集
2019/02/15 06:42