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

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

ただいまの
回答率

90.51%

  • Ruby

    7664questions

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

  • Ruby on Rails

    7265questions

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

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 283

renren643

score 197

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>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

    @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


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

class User < ApplicationRecord
  def generate_image_name
    self.image_name = loop do
      random_token = SecureRandom.urlsafe_base64(nil, false) + ".jpg"
      break random_token unless self.class.exists?(image_name: random_token)
    end
  end
end

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/24 23:09

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

    キャンセル

  • 2017/09/24 23:24 編集

    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を加えれば良いかと思います。

    キャンセル

  • 2017/09/24 23: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

    しかし、何故上記のようにするとうまくいくのかわかりません。差し支えなければ教えてください

    キャンセル

  • 2017/09/24 23:56

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

    キャンセル

  • 2017/09/25 01:13

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

    キャンセル

  • 2017/09/25 09:58

    そうです!

    キャンセル

  • 2017/09/25 20:37

    ありがとうございます!

    キャンセル

0

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/24 22:40

    回答ありがとうございます。
    はい、1対多とはなっていません。
    progateというサイトを見ながら、シナリオ通りそのまま作ったのでそういうことまで気が配れませんでした。
    1対多にするにはUserモデルとImageモデルを分け、後から、その両者を紐付けるというやり方でしょうか?

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

    これが増えていないんです。その理由がわかりません。

    キャンセル

  • 2017/09/24 22:44

    はい、同じ名前で画像が作成されているため、画像は上書き保存されます。そのため、増えないのが正常の動作となります。

    まずは、画像を追加してDBに貯めていくというシンプルな機能を作成し、そのあと、どうやったらUserと画像を紐づけられるかを考えた方が近道だと思います。

    最終的には画像パスとuserのidが入った画像テーブルができるはずです。

    キャンセル

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

  • ただいまの回答率 90.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Ruby

    7664questions

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

  • Ruby on Rails

    7265questions

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