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

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

ただいまの
回答率

90.33%

Rails:carrierwaveで確認画面から登録フォームに戻った時に画像を残しておきたい

受付中

回答 0

投稿 編集

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

traveler18

score 2

 前提・実現したいこと

ruby on railsでwebサイトを作っています。
ユーザー登録のプロフィール画像のアップロードに gemのcarrierwaveを利用しております。
登録画面から確認画面を一度挟んで、確認画面で確認ごに登録ボタンを押すことでユーザー情報を登録できるようにしております。登録画面から確認画面に進んだあと、フォームの内容を修正するために一度登録画面に戻る場合やバリデーションに引っかかった場合に、直前にアップした画像をそのまま残しておきたいのですが、画像が消えてしまいもう一度画像をアップしなければなりません。登録画面に戻ったあと、そのまま確認画面に進んだ時に写真をアップしたままにするにはどのように現状のコードを修正したらいいのかわかりません。ご教示をよろしくお願いいたします。
(画像の回転や切り抜きができるようにこちらのサイトも参照して実装してます。
https://tech.recruit-mp.co.jp/server-side/niche-rails-tips/)

 登録画面 _form.html.erb

<div class="form-inputs" id="image-cropper">
    <div class="col-sm-5">
      <%= f.label :profile_img do %>
        <span class="label label-danger">必須</span>
        プロフィール画像(本人写真)
        / profile picture
      <% end %>
      <p class="help-block">※待ち合わせの際に顔が分かるように、ご本人様のお写真をご使用ください</p>
    </div>
    <div class="col-sm-7">
      <%= f.file_field :profile_img, accept: 'image/jpeg,image/gif,image/png', class: 'cropit-image-input', required: true %>
      <%= f.hidden_field :profile_img_cache %>
      <div class="cropit-preview">
        <%= image_tag(@user.profile_img.url, class: "vanish") if @user.profile_img? %>
      </div>
      <div class="controls-wrapper">
        <div class="rotation-btns">
          <i class="fa fa-undo icon rotate-ccw-btn" aria-hidden="true"></i>
          <i class="fa fa-repeat icon rotate-cw-btn" aria-hidden="true"></i>
        </div>
        <div class="slider-wrapper">
          <i class="fa fa-picture-o icon icon-image small-image" aria-hidden="true"></i>
          <input type="range" class="cropit-image-zoom-input custom">
          <i class="fa fa-picture-o icon icon-image large-image" aria-hidden="true"></i>
        </div>
      </div>
    </div>
      <%= f.hidden_field :profile_img_data_uri %>
      <%= f.hidden_field :profile_img_data_uri_cache %>  
  </div>

 確認画面 confirm.html.erb

<div class="prof-attr">
          <label class="prof-label">
            <span class="label label-danger">必須</span>
            プロフィール画像(本人写真)
            / profile picture
          </label>
          <div class="prof-cnt prof-img">
            <%= image_tag @user.profile_img.url if @user.profile_img? %>
            <%= hidden_field_tag :"cache[profile_img]", @user.profile_img.cache_name %>
          </div>
        </div>

 Controller users_controller.rb

def new
      @user = User.new
  end

  def confirm
    @user = User.new(user_params) #POSTされたパラメータを取得
    # @user.profile_img.cache!

    render :new if @user.invalid?
  end

  def create
    auth = request.env["omniauth.auth"]
    if auth.present?
      if @auth = Authorization.find_from_auth(auth)
        user = @auth.user
        log_in user
        redirect_back_or user
      else
        @auth = Authorization.create_from_auth(auth)
        user = @auth.user
        log_in user
        remember(user)
        flash[:success] = "ユーザー登録に成功いたしました。"
        redirect_back_or user
      end
    else
        @user = User.new(user_params)
      begin
        @user.profile_img.retrieve_from_cache! params[:cache][:profile_img]
      rescue => e
        p e
      end
      if params[:back]
        render :new
        return
        elsif @user.save
        @user.send_activation_email
            flash[:info] = "アカウントを有効化するために送られてきたメールを確認してください。"
        UserHobby.create(:hobby_name => 'オールジャンル', :user_id => @user.id)
            redirect_to root_url
        return
        else
            render 'new'
        return
        end
    end
  end

 モデル user.rb

before_validation :set_profile_img_from_data_uri
・
・
・
def set_profile_img_from_data_uri
    if profile_img_data_uri != ''
        self.profile_img = data_uri_to_file(profile_img_data_uri)
end

 UserHelper users_helper.rb

def data_uri_to_file data_uri
        # データURIスキームを正規表現で分割
        data = data_uri.try do |uri|
          uri.match(%r{\Adata:(?<type>.*?);(?<encoder>.*?),(?<data>.*)\z}) do |md|
            {
              type:      md[:type],
              encoder:   md[:encoder],
              data:      Base64.decode64(md[:data]),
              extension: md[:type].split('/')[1]
            }
          end
        end
        return nil unless data

        # 画像のTempfileを作成
        temp_file = Tempfile.new('uploaded-data_uri').tap do |file|
          file.binmode
          file << data[:data]
          file.rewind
        end


        # 画像fileを作成
        ActionDispatch::Http::UploadedFile.new(
          filename: "data_uri.#{data[:extension]}",
          type:     data[:type],
          tempfile: temp_file
        )
    end

 試したこと

https://github.com/carrierwaveuploader/carrierwave#making-uploads-work-across-form-redisplays
gem carrierwaveの「Making uploads work across form redisplays」を参考に、
hidden_fieldを追加。

 確認済みのこと

・登録画面で画像アップロード後、切り抜き前の画像と切り抜いた画像が picture_uploader.rbのcache_dir
で指定したディレクトリで保存されること
ex) uploads/user/profile_img/仮user_id_1/オリジナル画像
uploads/user/profile_img/仮user_id_2/data_uri.png
・本登録ご、picture_uploader.rbのstore_dirで指定したディレクトリで画像ファイルが保存され、DBに data_uri.png(アップした画像の拡張子) という名前でprofile_imgカラムの値が更新されること。
uploads/user/profile_img/user_id/data_uri.png
・確認画面から登録画面に戻った時にはアップした画像は表示されているが、そのまま再び確認画面に進むと画像は表示されません。

 環境情報(FW/ツールのバージョンなど)

CentOS Linux release 7.4.1708 (Core) (さくらvps)
ruby: 2.4.3(rbenv)
rbenv 1.1.1-28-gb943955
rails 5.0.6
Phusion Passenger 5.2.3
Apache/2.4.6 (CentOS)

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

まだ回答がついていません

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