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

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

ただいまの
回答率

87.49%

画像がnilのまま投稿するとエラーになる

解決済

回答 1

投稿 編集

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

score 26

題名の通り、画像を空のまま投稿するとエラーが返ってきます。
Micropostモデルのimgカラムの中身がnilのまま投稿したら、
root_pathに飛んでflashを表示させたいのですがどうしたら良いのでしょうか。
ご教授よろしく御願い致します。
エラー内容
micropostモデルの中で下記実装中です。

validates :img,   presence:true

[試したこと]
MicropostsControllerのcreateアクションの中で下記コードを実装済。
redirect_to root_path if micropost_params == nil(3行目)

def create
    @micropost = current_user.microposts.build(micropost_params)
    redirect_to root_path if micropost_params == nil
    if @micropost.save
      flash[:success] = "投稿しました!"
      redirect_back(fallback_location: root_path)
    else
      flash[:danger] = "投稿に失敗しました!"
      @feed_items = current_user.feed.paginate(page: params[:page])
      render 'pages/home'
    end
 end

  private
    def micropost_params
      params.require(:micropost).permit(:img)
    end
[viewファイル]

<h4 class="modal-title">写真投稿</h4>      
<div class="modal-body">
   <% @micropost = Micropost.new unless @micropost %>
   <%= form_for(@micropost) do |f| %>
     <%= f.file_field :img, accept: 'image/jpeg,image/gif,image/png' %>
     <%= f.submit "投稿する", class: 'btn btn-primary' %>
   <% end %>
</div>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • siruku6

    2020/02/13 20:49 編集

    投稿formのviewファイルを質問内に追記していただいてもいいでしょうか?
    errorを見る限りでは、paramsの中にmicropostというkeyが存在しないせいでエラーになっているように見えます。

    キャンセル

  • jqk

    2020/02/13 20:59

    返信ありがとうございます。viewfile追加しました。
    因みに、画像を添付すれば、画像投稿はできます。

    キャンセル

回答 1

checkベストアンサー

+1

原因の調査結果

viewファイルを真似たところ、動作を再現することができました。
f.file_fieldについては、中身が入力されていない場合、その枠(今回でいうところの micropost)もない状態で処理がcontrollerに移るようです。

その結果、requireに失敗してしまいます。

ところが、text_fieldなどであれば、入力値が空であったとしても枠(今回はmicropost)が存在する状態で処理が行われるので、今回のようなエラーにはなりません。

つまり、file_field特有のバグのようです。

対策

ここで、対策としてfile_field以外の入力フォームを追加することでこの問題は回避できるのですが、micropostにはimg以外のカラムは存在しないのでしょうか??

他のカラムがあれば、その入力フォームをviewに追加すれば、requireに失敗するerrorは回避できそうです。

もしカラムがもう何もないようであれば、特に存在意義はないのですが、次のようなコードをviewに差し込んでおくことで、micropostの枠が生成されてrequireは成功するようになると思いますので試してみてください。

# これはだめだった(20200214判明)
= f.hidden_field :id

# こっちはどうでしょう?
= f.hidden_field :user_id, value: current_user.id

補足(以下、間違いでした)

今回は次のようなvalidationを設定していると思いますので、

validates :img, presence: true

次の1行は削除してもらって大丈夫だと思います。

redirect_to root_path if micropost_params == nil

これがなくても、次の条件が自動でfalseになるのでelse文の処理に入ります。

if @micropost.save

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/02/14 12:02

    あ、勘違いしてました。

    これ全部エラー文だと思ってましたが、後半はShunPさんの説明文でしたか、、、

    >No route matches [GET] "/microposts"
    micropostモデルのカラムはimgとuser_idだけです。

    そういうことであれば、routingエラーが発生しているようなので、routingエラーの全文と、rails routes コマンドの結果を見比べてみてください。
    分からなければ両方を掲載してもらえれば私か他の誰かが回答出来ると思います。

    頑張ってみてください~

    キャンセル

  • 2020/02/14 13:31 編集

    siruku6さん解決しました!!本当にケアしていただき有難う御座います!!

    [解決方法]
    ①言われた通りにviewに<%= f.hidden_field :user_id, value: current_user.id%>を追加。
    次にidが定義されていないというエラー文が表示されたので、
    viewに<% if user_signed_in? %>を追加(deviseを使用している為)。
    ②次に、No route matches [GET] "/microposts"というエラーが表示されたので、
    MicropostsControllerのcreateアクションのリダイレクト先を変更。
    redirect_back(fallback_location: root_path)→→redirect_to root_path
    ストロングパラメータで許可するのは、imgカラムだけでも大丈夫です。

    因みにredirect_to root_pathに変えた理由は、ただの勘です。
    どうしてこれでエラーが表示されなくなったのか、分かる範囲で良いので、
    ご教授頂きたいです。よろしく御願い致します。

    キャンセル

  • 2020/02/17 19:37 編集

    実は、私も`redirect_back(fallback_location: パス)`という記述を見るのは初めてで、ここは理解できていません。

    調べてみると、どうやらつい最近追加されたばかりのメソッドのようです(日本語の記事が少ない

    そして、このメソッドの機能としては、直前に開いていたページにリダイレクトさせることのようです。

    これはあくまでも予想なのですが、もしかしたら redirect_back() は直前に開いていたページに強制的に 「get リクエスト」で飛ばそうとするのかもしれません。
    そしてその遷移先が、「実は get 以外の postなどのrequestで表示されていたページ」だった場合、routingが存在しないためにエラーになってしまいます。

    この説明でなんとなくイメージできればいいなと思っています。。。

    キャンセル

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

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

関連した質問

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