質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

2回答

7785閲覧

【Rails JS】フォームで画像ファイルのプレビューをeditでも表示したい

besuko

総合スコア16

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2017/02/21 00:48

編集2022/01/12 10:55

###環境
Ruby(2.3.3)
Ruby on Rails(5.0.1)

gem
carrierwave(アップローダー)
cocoon(ネストフォーム)

保存先
Cloudinary

###保存されている画像ファイルを更新時に取得したい

こちらを参照してRailsの画像アップロードフォームにプレビューを表示させました。

枠内にプレビュー表示されます

新規登録時はこのままで問題ないのですが、現状edit(更新)画面では空欄のままとなっており事前に保存されている画像を枠内に表示させたいと考えております。

枠内にプレビュー表示されます
以下のJSファイルを編集が必要かと思いますが、どの部分を変更すれば良いのか教えて頂けませんでしょうか。。
なお、image(画像)モデルはshop(店舗)モデルにネストされています。

JavaScript

1$(document).on('change', ':file', function() { 2 var input = $(this), 3 numFiles = input.get(0).files ? input.get(0).files.length : 1, 4 label = input.val().replace(/\\/g, '/').replace(/.*\//, ''); 5 input.parent().parent().next(':text').val(label); 6 7 var files = !!this.files ? this.files : []; 8 if (!files.length || !window.FileReader) return; // no file selected, or no FileReader support 9 if (/^image/.test( files[0].type)){ // only image file 10 var reader = new FileReader(); // instance of the FileReader 11 reader.readAsDataURL(files[0]); // read the local file 12 reader.onloadend = function(){ // set image data as background of div 13 input.parent().parent().parent().prev('.imagePreview').css("background-image", "url("+this.result+")"); 14 } 15 } 16});

サーバーサイドはこのようになっております

ruby

1class Shop < ApplicationRecord 2 has_many :images, dependent: :destroy 3 accepts_nested_attributes_for :images, allow_destroy: true

ruby

1class Image < ApplicationRecord 2 belongs_to :shop, optional: true 3 mount_uploader :file, ImageUploader 4end

Ruby

1 def new 2 @shop = Shop.new 3 @shop.build_close_date 4 2.times { @shop.images.build } 5 end 6 7 def edit 8 @shop.close_date = CloseDate.new if @shop.close_date.blank? 9 end 10 11 def create 12 @shop = current_user.shops.build(shop_params) 13 respond_to do |format| 14 if @shop.save 15 format.html { redirect_to @shop, notice: '店舗情報を登録しました' } 16 format.json { render :show, status: :created, location: @shop } 17 else 18 format.html { render :new } 19 format.json { render json: @shop.errors, status: :unprocessable_entity } 20 end 21 end 22 end 23 24 def update 25 if @shop.update(shop_params) 26 format.html { redirect_to @shop, notice: '店舗情報を更新しました' } 27 format.json { render :show, status: :uploded, location: @shop } 28 else 29 format.html { render :edit } 30 format.json { render json: @shop.errors, status: :unprocessable_entity } 31 end 32 end 33end

HTML

1<%= simple_form_for(@shop, :authenticity_token => true, html: { multipart: true }) do |f| %> 2<div class="nested-field"> 3 <%= f.simple_fields_for :images do |image| %> 4 <%= render partial: 'image_fields', locals: {f: image} %> 5 <% end %> 6 <%= link_to_add_association "画像を追加", f, :images, :class => 'btn btn-primary' %> 7</div> 8<% end %>

HTML

1<div class="nested-fields form_time_selects imgInput"> 2 <div class="col-sm-2"> 3 <div class="input-group"> 4 <label class="input-group-btn"> 5 <span class="btn btn-primary"> 6 選択<%= f.file_field :file, :class => "uploadFile", :style => "display:none" %> 7 <%= link_to_remove_association("削除", f, {}) %> 8 </span> 9 </label> 10 <input type="text" class="form-control" readonly=""> 11 </div> 12 </div> 13 <%#= link_to_remove_association("削除", f, {}) %> 14</div>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moke

2017/02/21 02:04

ちょうどタイムリーに似たようなシステムを作っています。 Bootstrap File Input とfields_forを使って実装中なので、jsを1,2行に収めれると思います。需要があればコードを書きますが。。。
besuko

2017/02/21 02:10

有難うございます。コードのご掲載をお願いしても宜しいでしょうか。
moke

2017/02/21 02:56

まだ完成してないので少々お待ちをorz
moke

2017/02/23 04:23 編集

すみません急な用事が入って、報告が遅れました。一応完成しました。確認ですが、besuko様はuploadしたイメージがuploadした後も見えてそのままの画面で追加削除ができるようにしたいのですよね。 後気づかなかったのですがCarrierWaveを使っているのですか?
besuko

2017/02/23 04:30

いえ、全然問題ございません。はい、アップローダーはCarrierWaveを使っております。その後も試行錯誤をしていますが未だ解決出来ておりませんので、ご教示頂けますと幸いです。
moke

2017/02/23 04:44 編集

おお素早い回答、お待たせしてすみません、一応確認なのですが、uploadする画像が2つになっているのは区別するためなんですか?例えば外観と店長の写真とか?関係なければ、一つに複数アップロード可能とか、外観、内装、商品、店員とかカテゴリー分けかつ複数登録可能とかできますが。 あと当方attachementを使ってるので、読み替えていただく必要があるかもしれません
besuko

2017/02/23 04:52

初期状態で2つフォームがあるのは特に意味はございません。複数枚アップロード出来るようにしておりますが、現時点ではカテゴリー分けや決まったルールはございません。ただ保存出来る枚数に制限が無い状態にしてあります。
moke

2017/02/23 05:38

一応CarrierWave仕様で書いてみました。CarrierWaveを使ったことがないので間違ってたらすみません
guest

回答2

0

とりあえず、プロトタイプなのでグタグタです。需要があれば、そのうちgemにまとめます。
複数構造にしたり、shopからstaffにネストしてとかも可能です。
まず、rails-assets-bootstrap-fileinputを追加します。
めんどくさいのでrails-assetsを使います。

ruby

1gem file 2source 'https://rails-assets.org' do 3gem 'rails-assets-bootstrap' 4gem 'rails-assets-bootstrap-timepicker' 5gem 'rails-assets-bootstrap-html5sortable' 6gem 'rails-assets-bootstrap-fileinput', '~> 4.3.8' 7gem 'rails-assets-bootstrap-tagsinput' 8end

application.css
application.js
は環境に合わせて修正してください

bundle install
して
rake assets:precompile

editでそのまま編集できるように

jsは外部に書いた方がかっこいいけどturbolinksと競合しないようにベタがき

ruby

1shops/edit.html.erb 2<%= from_for(@shop) do |f| %> 3<%= f.text_fields :shopname %> 4~ 5<%= f.fields_for :images_attributes do |image| %> 6<%= image.file_field :file,class: 'file-upload',name: "#{image.object_name}[file]",'data-json'=>file_input_jbuilder(image.object.file) %> 7<%= javascript_tag do %> 8$(".file-upload").fileinput($(this).data('json')); 9<% end %>

jbuilderがうまく使えなかったのでto_jsonで妥協
imageの削除用のmethodをformat.jsで作っておくこと
パラメータは必要最低限,他にカスタムしたいときは
ここら辺を参照

ruby

1application_helper.rb 2def file_input_jbuilder(images) 3images=Array(images) 4({"initialPreview"=>images.map{|image|image.thumb.url}, 5"initialPreviewAsData"=>true, 6"initialPreviewConfig"=>images.map{|image| {"caption"=>image.original_filename,"width"=> '120px',"url"=> url_for({controller: :images,action: :delete,id: image.id}),"key"=> 100}}}).to_json 7end

最後にコントローラのstrong_paramaterを修正

ruby

1shops_controllers.rb 2~ 3def shop_params 4params.require(:shop).permit(:shopname,~,images_attributes: [:file])

多分これでオッケーです。

投稿2017/02/23 05:26

編集2017/02/25 01:32
moke

総合スコア2241

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

besuko

2017/02/24 01:27

有難うございます! 先日より取り組んでいるのですが、一部エラーが出てしまい且つ修正が出来ずにおります。。 syntax error, unexpected ':', expecting '}' (SyntaxError) ...px',"url"=> url_for{controller: :images ,action: :delete ,id... ... ^
moke

2017/02/24 02:29 編集

すみません ブロック渡しになってしまっているようです。 hashを()でくくってください url_for({controller: :images ,action: :delete ,id: image.id})
besuko

2017/02/24 03:03

有難うございます。 続いて同ヘルパーの「map」の部分で躓いております。 mapというものが「配列内のオブジェクトをフォーマットするもの」ということは分かりましたが、それをRubyで扱う方法が分からずにおります。 ヘルパー内に書かれている内容の意味はJSONというものを学べば理解できる内容なのでしょうか。 NoMethodError in Shops#edit undefined method `map' for #<ImageUploader:0x007fa4be71ae48> Did you mean? tap
moke

2017/02/24 14:30

ごめんなさい、terateilの更新通知が出ませんでした。 Carrer wave だと1つのレコードに1つのファイルしかアップロード出来ないのですね。勉強不足でした。 一応修正しておきます。
besuko

2017/02/25 01:13

Carriewaveだとそういった制限があるのですね。 こちらの環境にご配慮頂き感謝致します。 修正頂きましたコードも、同様に「undefined method `map'」と出てしまうのですが「map」というメソッドをどこかで定義しておく必要がございますでしょうか。
moke

2017/02/25 01:34

いやーmapはarrayのmethodです arrayを期待して作っていたので、 引数imagesが単体の場合、Array(Images)で無理やり arrayにしてください
besuko

2017/02/25 03:33

mapはRubyのメソッドなのですね、、知らずに見当違いな質問をしてお恥ずかしい限りです。 「shop_images=Array(shop_images)」の追加で上記のエラーは出なくなりました。 またshop/edit画面にも画像は表示されませんが既存ファイルの数だけフォームが表示されているので、かなりゴールに近づきいているように思えます。
moke

2017/02/25 06:36 編集

image.thumb.url を image.url にしてみてください また、image.urlが相対パスになっていないか確認してください ここの値はhttpから始まる絶対パスでないと動かないようです。 相対パスの場合、images.map{|image|['あなたのroot_path',image.thumb.url].join('/')}, と置き換えてみてください
besuko

2017/02/26 09:08

開発・本番ともファイルの保存はCloudinalyというクラウドの画像管理サービスを使っております。 保存されたファイルは「http://res.cloudinary.com/hvrpgrvpi/image/upload/v1487*******/***.jpg」といったURLとなります。これは絶対パスという理解で良いのでしょうか。 念のため本番環境(heroku)でも試してみましたが画像は表示されずにおります。 JSのコンソールを確認してもエラーは表示されず、誤り箇所は特定出来かねている状況でございます。 なお、現状helperはこのようにしております。 (imageモデルのfileカラムに保存されたデータを呼び出す) def file_input_jbuilder(image) images = Array(images) ({"initialPreview"=>images.map{|image|image.file.url}, "initialPreviewAsData"=>true, "initialPreviewConfig"=>images.map{|image| {"caption"=>image.file,"width"=> '120px',"url"=> url_for(@shop), "key"=> 100}}}).to_json end
moke

2017/02/26 09:46

この場合imageがfileに相当するので image.file.urlではなく image.urlで大丈夫です。 デバッグするか fileimputのdata-json属性をみて image.urlがどんな値を表示するか調べ 例えばimage.urlが'v1487*******/***.jpg'と表示されれば images.map{|image|[’http://res.cloudinary.com/hvrpgrvpi/image/upload’,image.url].join('/')} といった感じに置き換えてください。
besuko

2017/02/27 04:08

有難うございます。 デバッグから値を確認する方法は分からずにおります。。 「data-json属性」とはソートから確認できるのでしょうか。 グーグルで調べても分からずにおり初歩的過ぎる質問で申し訳ございません。。
moke

2017/02/27 04:30 編集

Webブラウザから表示中のHtmlのソースを読めばわかります。 対象を右クリックして検証とか なければソースを表示とかおしてみて下さい。
besuko

2017/02/28 03:18

ソースで該当箇所を確認出来ました。 image.urlの末尾には「'v1487*******/***.jpg'」と表示されておりますので、helperには images.map{|image|[’http://res.cloudinary.com/hvrpgrvpi/image/upload’,image.url].join('/')} と設置致しました。 それでも残念ながらファイルは表示されずにおります。 せっかく親身に教えて頂いているのに結果が出ずに申し訳ございません。 Shop/edit.html.erb (HTMLソース) <h1>Editing shop</h1> <p id="image_130"> <img width="200px" src="http://res.cloudinary.com/hvrpgrvpi/image/upload/v1487902****/130.jpg" alt="130" />
moke

2017/02/28 03:45

そのurlをブラウザに打ち込むとちゃんと表示されますか? ログインとか必要ないですかね? あと末尾がという表現が気になります。 htmlのinputタグてclassがfile-upload のもののdata-json内に表示されているデータです。もう一度確認下さい
besuko

2017/02/28 03:56

はい、edit画面はログイン時のみアクセス可能なようにしてあります。 (ログイン機能はDeviseを用いています) 改めてソース(HTML)を見たところ、date-json箇所には以下のように表示されていることを確認致しました。 <input class="file-upload" name="shop[images_attributes][3][file]" data-json="{&quot;initialPreview&quot;:[],&quot;initialPreviewAsData&quot;:true,&quot;initialPreviewConfig&quot;:[]}" type="file" id="shop_images_attributes_3_file" />
besuko

2017/02/28 04:16

失礼致しました。 先ほどのソースは別の表示箇所でございました。 shop/_form.html.erb <%= image.file_field :file ,class: 'file-upload',name: "#{image.object_name}[file]",'data-json'=>file_input_jbuilder(image.object.file) %> に該当する箇所は以下のソースです。 (同一ファイルを複数のサイズで保存しているので煩雑になってしまっております。。) ソース(HTML) <input class="file-upload" name="shop[images_attributes][3][file]" data-json="{&quot;initialPreview&quot;:[&quot;http://res.cloudinary.com/hvrpgrvpi/image/upload/http://res.cloudinary.com/hvrpgrvpi/image/upload/v1487902***/130.jpg&quot;],&quot;initialPreviewAsData&quot;:true,&quot;initialPreviewConfig&quot;:[{&quot;caption&quot;:{&quot;uploader&quot;:{&quot;url&quot;:&quot;http://res.cloudinary.com/hvrpgrvpi/image/upload/v1487902***/130.jpg&quot;,&quot;standard&quot;:{&quot;url&quot;:&quot;http://res.cloudinary.com/hvrpgrvpi/image/upload/c_fill,g_north,h_150,w_100/v1487902***/130.jpg&quot;},&quot;thumbnail&quot;:{&quot;url&quot;:&quot;http://res.cloudinary.com/hvrpgrvpi/image/upload/c_fit,h_200,w_200/v1487902***/130.jpg&quot;},&quot;_100x100&quot;:{&quot;url&quot;:&quot;http://res.cloudinary.com/hvrpgrvpi/image/upload/b_rgb:fff,c_pad,h_100,w_100/v1487902***/130.jpg&quot;},&quot;_280x280&quot;:{&quot;url&quot;:&quot;http://res.cloudinary.com/hvrpgrvpi/image/upload/b_rgb:fff,c_pad,h_280,w_280/v1487902***/130.jpg&quot;},&quot;_540x540&quot;:{&quot;url&quot;:&quot;http://res.cloudinary.com/hvrpgrvpi/image/upload/b_rgb:fff,c_pad,h_540,w_540/v1487902***/130.jpg&quot;},&quot;_800x800&quot;:{&quot;url&quot;:&quot;http://res.cloudinary.com/hvrpgrvpi/image/upload/b_rgb:fff,c_pad,h_800,w_800/v1487902***/130.jpg&quot;}},&quot;identifier&quot;:&quot;image/upload/v1487902***/130.jpg&quot;,&quot;resource_type&quot;:&quot;image&quot;,&quot;storage_type&quot;:&quot;upload&quot;,&quot;version&quot;:&quot;1487902***&quot;,&quot;filename&quot;:&quot;130.jpg&quot;,&quot;public_id&quot;:&quot;130&quot;,&quot;format&quot;:&quot;jpg&quot;},&quot;width&quot;:&quot;120px&quot;,&quot;url&quot;:&quot;/shops/3&quot;,&quot;key&quot;:100}]}" type="file" id="shop_images_attributes_3_file" />
moke

2017/02/28 06:56

ファ?ゲフンゲフン さすがに['http://res.cloudinary.com/hvrpgrvpi/image/upload/http://res.cloudinary.com/hvrpgrvpi/image/upload',image.url].join('/') はネタだと思いたい とりあえず。 images.map{|image|image.url} のままでよかったようですね。 ちなみに、そのurlとは http://res.cloudinary.com/hvrpgrvpi/image/upload/v1487902****/130.jpg のことです。これをブラウザに打ち込んで画像が表示されないようなら それが問題です。res.cloudinary.comに行って表示の仕方を調べてください。
besuko

2017/03/01 02:08

有難うございます。 そうですね、URLを直に打ち込んだ場合は表示されますので、どこかおかしい部分があるのだと思います。 ゴールまでの道筋が全くイメージ出来ず心が折れそうですがもう少し粘ってみます。。
guest

0

うーん、もうちょっと頑張って調べましょうよ。
とりあえず環境を整えアップロー画面をべたのHTMLで作成し、デバッグ実行してみるとアップロードファイルを取得できましたが。

index.html.erb

html

1<form id="my-awesome-dropzone" class="dropzone" action="/shops/" method="post"> 2 <div class="dropzone-previews" style="width:100%; height:100%"></div> 3 <input type="email" name="username" /> 4 <input type="password" name="password" /> 5 <button type="submit">Submit data and files!</button> 6</form> 7<script> 8 Dropzone.autoDiscover = false; 9 Dropzone.options.myAwesomeDropzone = { 10 autoProcessQueue: false, 11 uploadMultiple: true, 12 parallelUploads: 100, 13 paramName: 'fuga', 14 maxFiles: 100, 15 init: function () { 16 var myDropzone = this; 17 this.element.querySelector("button[type=submit]").addEventListener("click", function (e) { 18 e.preventDefault(); 19 e.stopPropagation(); 20 myDropzone.processQueue(); 21 }); 22 } 23 } 24 var dropzone = new Dropzone('#my-awesome-dropzone'); 25</script>

shop_controller.rb

ruby

1class ShopsController < ApplicationController 2 protect_from_forgery with: :null_session 3 4 def fuga_params 5 params.require(:fuga).permit( 6 :name, :description, :price, 7 images_attributes: [:fuga] 8 ) 9 end 10 11 def index 12 hoge = 3 13 end 14 15 def create 16 params[:fuga].each do |idx| 17 # アップロードされたファイルのファイル名をコンソールに表示 18 logger.debug(params[:fuga][idx].original_filename) 19 end 20 hoge = 3 21 22 end 23end

ブラウザー画面
イメージ説明

デバッグ画面
イメージ説明

投稿2017/02/21 10:21

編集2017/02/21 10:23
turbgraphics200

総合スコア4267

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

besuko

2017/02/23 01:55

そうですね、、これまでもとてもご親切にして頂け甘えておりました。 それにも関わらず環境の再現からデバッグのフィードバックまで教えて頂き本当に感謝致しております。 残念ながら私の環境では同じように動かずにおります。 何か他に要因があるかと思いますので、もう少し粘ってみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問