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

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

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

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

Ruby on Rails

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

Q&A

解決済

2回答

266閲覧

新しく画像を投稿すると全ての他の投稿にも新しい投稿画像が反映されてしまう

renren643

総合スコア279

Ruby

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

Ruby on Rails

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

0グッド

0クリップ

投稿2017/09/24 13:12

railsでツイッター系のサイトの開発をしているのですが、画像を投稿すると他の全ての投稿にも新しい画像が反映されてしまいます。
どこかで間違えがあると思いますので教えていただければ幸いです。

class UsersController < ApplicationController def index @users = User.all end def show @user = User.find_by(id: params[:id]) end def new @user = User.new end def create @user = User.new( name: params[:name], email: params[:email], content: params[:content], image_name: "noimage.jpg" ) if params[:image] @user.image_name = "#{@user.id}.jpg" image = params[:image] File.binwrite("public/user_images/#{@user.image_name}", image.read) end if @user.save flash[:notice] = "ユーザー登録が完了しました" redirect_to("/users/#{@user.id}") else render("users/new") end end def edit @user = User.find_by(id: params[:id]) end def update @user = User.find_by(id: params[:id]) @user.name = params[:name] @user.email = params[:email] @user.content = params[:content] if params[:image] @user.image_name = "#{@user.id}.jpg" image = params[:image] File.binwrite("public/user_images/#{@user.image_name}", image.read) end if @user.save flash[:notice] = "ユーザー情報を編集しました" redirect_to("/users/#{@user.id}") else render("users/edit") end end end

index.html.erb↓

<div class="row"> <% @users.each do |user| %> <div class="col-md-6"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title text-center"><%= link_to(user.name, "/users/#{user.id}") %></h3> </div> <%# ここはeach文の@postsがあるので@post.image_nameではなくpost.image_nameでいい%> <img src="<%= "/user_images/#{user.image_name}" %>" alt="" width="265" height="318" class="img-thumbnail img-post"> <button type="button" class="btn btn-warning"><%= link_to("詳細", "/users/#{user.id}") %></button> </div> </div> <% end %> </div>

new.html.erb↓

<div class="row"> <div class="col-sm-8 col-sm-push-4"> <h2 class="text-center"><strong><em> 研究者として登録</em></strong></h2> <%= form_tag("/users/create", {multipart: true}) do %> <div class="form-group"> <label for="Inputimage">写真</label> <input type="file" class="form-control" id="Inputimag" name="image"> </div> <button class="btn btn-warning" type="submit" value="投稿">登録</button> <% end %> </div>

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

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

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

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

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

guest

回答2

0

ベストアンサー

ruby

1 @user = User.new( 2 name: params[:name], 3 email: params[:email], 4 content: params[:content], 5 image_name: "noimage.jpg" 6 ) 7 8 if params[:image] 9 @user.image_name = "#{@user.id}.jpg" 10 image = params[:image] 11 File.binwrite("public/user_images/#{@user.image_name}", image.read) 12 end

newの段階ではidはnullなので、image_nameは全て同じ値になりそうです。
今の作りを変えないなら、ifの前に@user.saveをするかuniqueな値を発行する処理(generate_image_name)を入れると良いかと思います。

ruby

1class User < ApplicationRecord 2 def generate_image_name 3 self.image_name = loop do 4 random_token = SecureRandom.urlsafe_base64(nil, false) + ".jpg" 5 break random_token unless self.class.exists?(image_name: random_token) 6 end 7 end 8end

投稿2017/09/24 13:34

編集2017/09/24 13:36
akichim21

総合スコア93

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

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

renren643

2017/09/24 14:09

回答ありがとうございます。 「ifの前に@user.saveをする」とは if params[:image]の上に@user.saveを記述するだけですか?
akichim21

2017/09/24 14:25 編集

unless @user.save render("users/new") end ifの前に上記を追加するか if params[:image] @user.generate_image_name image = params[:image] File.binwrite("public/user_images/#{@user.image_name}", image.read) end ifの中を上記のようにして、Userクラスにgenerate_image_nameを加えれば良いかと思います。
renren643

2017/09/24 14:52

createアクション内で以下のようにすると解決しました。ありがとうございました。 unless @user.save render("users/new") end if params[:image] @user.image_name = "#{@user.id}.jpg" image = params[:image] File.binwrite("public/user_images/#{@user.image_name}", image.read) end しかし、何故上記のようにするとうまくいくのかわかりません。差し支えなければ教えてください
akichim21

2017/09/24 14:56

User.newの段階ではidはnullの状態で、image_nameが全て同じ値になるからです。 @user.saveするとDBに保存され、id = 1,2,3とユニークな値になるため解決します。
renren643

2017/09/24 16:13

@user.saveが成功すると、(それに伴い固有のidが付与されるため、それに基づく画像が)DBに保存され、失敗するとusers/newにレンダーされます、ということでよろしいでしょうか?
renren643

2017/09/25 11:37

ありがとうございます!
guest

0

そもそも、UserモデルとImageモデルを分けるべきなのではないですか?
こちらのコードを読む限り、Userにつき一つの画像しか保持できないよう作りになっているように見えます。

UserとUserが投稿した画像が1対多の関係になるリレーションを構築すべきでしょう。

大前提として、画像を投稿する度にpublic/user_images/配下に画像ファイルが増えていくはずですが、増えていくのは確認できていますでしょうか?

投稿2017/09/24 13:30

mtdsnsk

総合スコア789

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

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

renren643

2017/09/24 13:40

回答ありがとうございます。 はい、1対多とはなっていません。 progateというサイトを見ながら、シナリオ通りそのまま作ったのでそういうことまで気が配れませんでした。 1対多にするにはUserモデルとImageモデルを分け、後から、その両者を紐付けるというやり方でしょうか? >画像を投稿する度にpublic/user_images/配下に画像ファイルが増えていくはずですが、増えていくのは確認できていますでしょうか? これが増えていないんです。その理由がわかりません。
mtdsnsk

2017/09/24 13:44

はい、同じ名前で画像が作成されているため、画像は上書き保存されます。そのため、増えないのが正常の動作となります。 まずは、画像を追加してDBに貯めていくというシンプルな機能を作成し、そのあと、どうやったらUserと画像を紐づけられるかを考えた方が近道だと思います。 最終的には画像パスとuserのidが入った画像テーブルができるはずです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問