Rails初心者によるはじめてのWebアプリ制作日記 Vol.3 -投稿確認画面編-

2018-05-05


前回、投稿機能の追加が出来ました。
メンターの「投稿確定前に、内容の確認画面があるほうがいいよね」の一言を受け、今回は確認画面を実装します。

確認画面

確認画面の機能は以下の通り。

  • 投稿フォームを入力し確認ボタンを押したら投稿後の画面が見られる(タイトル、本文、画像を表示)
  • 確認画面から戻るボタンを押すと投稿フォーム画面に戻る
  • 戻った後の投稿フォームには入力した内容が保持されている
  • 確認画面から投稿と関係ない画面に遷移した場合は、保持していた内容は消す
  • 確認画面から登録ボタンを押すとデータが登録される

 

確認画面へのデータの持ち回し方法

確認画面を挟むということは、投稿フォームの内容を確認画面に渡してあげる必要がありますので、まずはデータの渡し方について教えてもらいました。

方法は2通り
1.hidden(隠しフォーム)で渡してあげる方法
2.sessionで渡してあげる方法

hiddenを使えば簡単だが、非表示なだけでブラウザにデータは送られておりユーザから改ざんが出来てしまい、悪意あるデータを入れられる可能性もあるので、投稿などではあまり使わない方が良い。
一般的にははsessionを使用すると教えて頂いたので、私もsessionを使うことにしました。

ちなみにsessionは簡単にいうとWebブラウザを閉じるまでデータを保存してくれるものです。
sessionこのあとのログイン機能でも活躍しますし、Webアプリでは大事な機能の一つだと思います!

 

sessionに値を入れる

railsでのsessionの書き方は
session[キー] = 値
なので、確認画面に行くタイミングで
session[:posts]にフォームの内容を入れるようにしました。

余談ですが、
「何か使い方を調べる時は先ずはドキュメントを見なさい!基本的にここに書いてあるから」
「過去にハマって何時間も調べたけど、ドキュメント見たら最初に書いてあったとかあったから」
と実体験を交えてメンターからアドバイス頂きました。

確かについついQiitaとか人のブログとかで検索しちゃう…
まずは公式ドキュメントですね!肝に命じます!

ちょっと話がそれましたが、戻しまして
sessionに値を入れて確認画面を作りました。

あとは投稿ボタンを押したら、createを呼びDBに反映させて、
登録終わったらsessionの値を消したらオッケー!

def create
  @post = Post.new(session[:posts])
 @post.save
 session[:posts] = nil
end

いざテストして見たら…
DBに画像データだけ反映されない!!???だから一覧画面で画像が見えない
なんで???
ってことで原因を調べます。

デバックしてみて、session[:posts]には値があるけど、インスタンス化した@postに時点で画像データが消えてる!!
でもなんで??

色々ググって見たり、一旦諦めて一晩寝て次の日にまた調べてみたり。。。
なんて数日格闘したがお手上げなので、メンターにヘルプ要請

Skypeで聞いたら数時間で解決策ソースが帰ってきました。
凄い!早い!感動!

結論は画像アップロードで使用したgem「carriewave」のソースを理解していないとダメだったようです・・・
便利さの弊害がここに現れました。

carriewaveの詳しい仕組みは今の時点では理解できていないのですが、どうやらアップロード時にDB反映前にキャッシュという一時保存場所に画像が保存されるので、その情報をsessionに入れる必要があるとかなんとか・・・

Qiitaで参考になることを書いてくださている方がおりました。

結局、確認画面に行くタイミングで画像用のsessionを用意し、そこにキャッシュから画像名を入れまして

 session[:picture_cache_name] = @post.picture.cache_name

登録時に画像名を@post変数にいれることで、無事にDBに反映され一覧画面からも見られるようになりました!!!

def create
    @post = Post.new(session[:posts])
    @post.picture.retrieve_from_cache!(session[:picture_cache_name])
    @post.save
    session[:posts] = nil
    session[:picture_cache_name] = nil
    redirect_to posts_path
  end

ここまで来るのに大変だった・・・
ゆくゆくはgemも理解できるようにしないといけないですね。

さて、確認画面からの登録ができたので、戻る機能も追加します。

 

確認画面からの戻るボタンの設置

戻るボタンを設置し、遷移先を新規投稿画面にします。
その際にフォームの初期値をsessionに格納されている投稿内容を表示させればOK

でもこのままだと、新規投稿ボタンからきた場合も、戻るボタンからきた場合も同じ新規投稿画面を使うので、どの画面から来たのかを判断させてフォームの初期値を入れるようにしないとエラーを出します。

なので、戻るボタンには戻るボタンから来たのがわかるように目印を入れます。
ここではhiddenで隠しデータを渡してあげます。
viewに下記のように記載すれば、戻るボタンを押した時にpageをキーとして”confirm”という値が渡ります。
このキー名と値はなんでもいいです。

<%= form_for :post, url: posts_new_path do |f| %>
  <%= hidden_field_tag :page, "confirm" %>
  <%= f.submit("戻る") %>
<% end %>

これでボタンを押した時に値が渡るので、新規投稿の時に呼ばれるnewコントローラーで条件分岐をします。
ボタンの値がある、かつsessionの値がある時はsessionの値を初期表示する。
ない時はsessionの値を空にする。

値がない時にsessionの値を空にしているのは、確認画面以外から来た時は初期化をするためです。

def new
    #確認画面の戻るボタンから来た時はセッションに値をフォームに表示する
    if params[:page] == "confirm" && session[:posts]
      @post = Post.new(session[:posts])
      @post.picture.retrieve_from_cache!(session[:picture_cache_name])
    else
      #確認画面以外から来た時はセッションを消す
      session[:posts] = nil
      session[:picture_cache_name] = nil
    end
  end



これで戻るボタン機能もできたので、当初予定していた下記機能はすべて完成です!!!

  • 投稿フォームを入力し確認ボタンを押したら投稿後の画面が見られる(タイトル、本文、画像を表示)
  • 確認画面から戻るボタンを押すと投稿フォーム画面に戻る
  • 戻った後の投稿フォームには入力した内容が保持されている
  • 確認画面から投稿と関係ない画面に遷移した場合は、保持していた内容は消す
  • 確認画面から登録ボタンを押すとデータが登録される



基本的な投稿機能は完成したので、次はログイン・ログアウト機能を実装します!!
この時点では削除と編集機能は忘れていたので・・・後ほど。笑

次回に続く!!!