3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Rails]ajaxでpostアクションを叩いたらsessionが拾えなかった。

Last updated at Posted at 2019-09-14

どうもこんばんは、Rails学習2〜3ヶ月くらいのChihaです。
タイトル通り、jQueryからajaxでアクションを叩いて動かすと、それまで定義してきたsessionの値が拾えなくなる現象に遭遇&解決したので、ざっくりと書きます。

開発環境

  • Ruby on Rails 5.2.2
  • Ruby 2.5.1
  • jQuery

概要

ajaxからのpostリクエストを叩くと、アプリ側に持たせていたsessionの値が取得できなくなった。

signup.js
//何かしらの処理後
$.ajax({ 
          url: "/signup",
          type: "POST",//コントローラのアクションをpostで叩く
          data: {
            //送るデータとか
          },
          async: false //今回は同期通信でした
        })
signup_controller.rb(例)
#前のページでの入力項目をsession保存
def before_page_content
  session[:birthyear] = profile_params[:birthyear]
  session[:birthmonth] = profile_params[:birthmonth]
  session[:birthday] = profile_params[:birthday]
end

#ajaxで叩くcreateアクション
#/signup(method: :post)
def create
  ※下のcreateが失敗する
  @profile = Profile.create(
  birthyear: session[:birthyear],
  birthmonth: session[:birthmonth],
  birthday: session[:birthday]
  )
end

こんな感じのコードでjsから直接postメソッドのアクションを叩くと、それまでに取得して来ることができたはずのsessionの値が全部nilになっていた。そりゃ当然失敗する。

ターミナル
ActionController::InvalidAuthenticityToken

エラーはこういうのが出ました。

解決策

signup.js
//何かしらの処理後
$.ajax({ 
          url: "/signup",
          type: "POST",
          data: {
            //送るデータとか
          },
          //下の記述を追記
          beforeSend: function(xhr) {
            xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
          },//ここまで
          async: false
        })

これで無事にcreateアクションでsessionの値を拾って処理ができるようになりました。

Rails not reloading session on ajax post
【Rails API】ActionController::InvalidAuthenticityTokenの解決方法
外部からPOSTできない?RailsのCSRF対策をまとめてみた

解決はこの辺りを参考にしました。
どうやら、RailsでのCSRF対策にjsからget以外のメソッドを叩いたのが悪かったようです。
【Rails API】ActionController::InvalidAuthenticityTokenの解決方法
詳しい理由とCSRFについてはこの記事に書かれてます。

トラブルの経緯

スクールでの開発にて、wizard形式(複数ページに渡りユーザー情報を入力させ、最後のページで一括createする形式)でのユーザー登録機能を実装していた時の話。
各ページで入力された値は、sessionとしてアプリ側に預ける形に(詳しくはそのうち)。
最終ページでクレジットの情報を登録する必要があったため、payjpを利用することに。

payjpでは、ユーザーが入力したクレジット情報をjavascript経由でpayjpに送り、トークンの情報を返す処理を行うことで、クレジット情報をRails側で使用せず、トークンを用いたユーザーのクレジットカード登録機能の実装、使用が可能となります。
こちらについては詳しくはpayjp.jsのリファレンス(カード情報のトークン化)で。

というわけで、最終ページでcreateではなく、payjp.jsでのトークン取得を経てcreateする形で実装することに。

つまり、jsでの処理を経由してpayjpからのトークンを取得したのち、トークンをjsから投げつつ、postメソッドのcreateアクションを叩く、という感じでの実装を考えた。

ここでjsからcreateアクションを叩くとsessionが一つも取得できなくなっていた。
要するに上記の症状が発生していた。

js側に記述を書き足すと解決した。

という流れになります。

かなりアバウトな感じになりましたが、詳しくは上記の参考記事にて。
クレジットカード登録を含めたwizard形式でのユーザー登録フォームの実装については、長くなりそうなので後日ということで。。。

最後に

引き続き気まぐれにトラブルや知った技術などを忘備録として書いていこうと思います。
まだまだ右も左もあやふやなド初心者ですので、より良いコード、間違った点などがあればご教授頂けると幸いです。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?