LoginSignup
9
10

More than 5 years have passed since last update.

rails5 apiモードで、deviseとdevise_token_authを両方とも使いたかった欲張りな人の話

Posted at

背景

ネイティブアプリが使うapiをrails apiモードで書いてた。初めはwebサイト側で何かしら書く必要なんて無いと思ってたんだけど、よく考えたらパスワードのリセットとかのプロセスをwebサイトで書く必要があることに気づいてとても焦った話です。一通り調べてもぴったりと解決に導いてくれた記事がないのでまとめてました。

大まかな流れはこの記事と同じなんだけど、自分の場合は「エラーその2」の後に、まだハマるポイントがあったのでその補強になればと思ってます。

一応認証には、devise_token_authを使っている。devise側が

api only appではdeviseじゃなくて、devise_token_auth使ってください

ってお願いしてる関係もあってdevise_token_authを使うことにしました。

deviseでviewを作りたかったのは、passwordをリセットするところの入力フォームのみ。これだけのためにすごくハマったから、もしかしたら別の効率のいいやり方があるのかもしれません。rails歴たかが2ヶ月の自分としては、0から実装には踏み切れなかったのですが、これは少し反省してます。笑

前提

devise_token_authで追加のパラメタを許可する必要があったので、そのinitiallizerで次の設定をしています。

app/controllers/application_controllers.rb

class ApplicationController < ActionController::API
  include DeviseTokenAuth::Concerns::SetUserByToken

  before_action :configure_permitted_parameters, if: :devise_controller?


  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:additonal, :params])
  end
end

問題点

Rails5 + APIモードで後からdeviseを使おうとした時のエラー対応にもあるように、apiモードでdeviseのviewを呼び出そうとすると色々問題が発生します。csrf対策とかはapiモードには組み込まれていないし、、

この方の書かれている通りに、実装するとdevise_token_authでsign_upをしようとした時にエラーがでます。なので、以下の通りに実装してください。

1. undefined method 'flash' for#ActionDispatch::Request に対して

まずこのエラーが出ると思います。flashメッセージが出ないみたいなので、それ用のmodule(?)を追加してあげます。

config/application.rb
config.middleware.use ActionDispatch::Flash
  1. undefined method `protect_against_forgery?' for # に対して

次にでてくるエラーはこれかと思います。ここまでは先ほどの方の記事と同じです。csrf対策をしないといけないので、親のコントローラーを変更してあげます。

config/initializes/devise.rb
config.parent_controller = 'ActionController::Base'

strong parameterでエラーが出る

  1. のエラーを解消すると、deviseはapplication_controllers.rbを経由せずに、直接ActionController::Baseを継承するようになります。そのため、前提の部分で定義していた、strong parameterへの追加の部分が読み込まれなくなります。これを解消するのが地味に大変でした。

色々試行錯誤をした結果、devise_token_authのリセット用のコントローラーをoverrideする形で解決することにしました。次のように書いてあげれば、同様にこのエラーを解消できるかと思います。

app/controllers/registrations_controller.rb
class RegistrationsController < DeviseTokenAuth::RegistrationsController
  # GET /users/sign_up
  def create
    super
    @resource = resource_class.new(sign_up_params)
  end

  private
  def sign_up_params
    params.permit(
      :add,
      :additional,
      :params,
      :wanna,
      :permit
    )
  end
end

これが僕の考えた中では最適なやり方でした。もっといいやり方は100%あるはずなので、教えて頂けると幸いです。

9
10
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
9
10