LoginSignup
0
0

アクション間で同じインスタンス変数を使い回す方法

Last updated at Posted at 2023-07-23

本記事の内容

アクション間で同じインスタンスを使いたいことがありました。
今回は、アクション間で同じインスタンス変数を使い回す方法を解説しています。

要件

1.ユーザー登録画面では、ユーザー名とメールアドレスのみを入力
1.png

2.入力されたメールアドレス宛に確認コードを送信、ユーザーが確認コードを入力する
4.png

このように、「ユーザー名・メールアドレス・確認コード」の3つを同じFormオブジェクトで管理しているが、別々のviewでそれぞれ入力したい場合があります。
この時、ユーザー登録画面から確認コード入力画面にリダイレクトするため、
ユーザー登録画面で作成したインスタンス変数は本来ならば、消えてしまいます。
今回は、ユーザー登録画面で入力された内容を保持して確認コード入力画面に遷移できるようにしたいと思います。

実装方法

結論としては、セッションを用います。
リダイレクト前にインスタンスをセッションに詰め、リダイレクト先でセッションから再度インスタンスを作成します。

def create
    〜〜(バリデーションチェックなど)〜〜
  # インスタンス変数をセッションに詰める
  session[:user_form] = @user_form
  redirect_to verify_email_path
end

def verify_email
  # セッションから再度インスタンスを作成
  @user_form = UserForm.new(session[:user_form])
end

しかし、これだけだと下記画像のような、errosという属性がないというエラーが発生します。
属性なし.png

これは、バリデーションチェックした後では、自動でインスタンス変数にerrorsvalidation_contextという属性が追加され、これに対応するFormオブジェクトのセッターがなく値をセットできないことが原因です。
binding.pryで確認した@user_form

{"errors"=>{}, "name"=>"テスト", "email"=>"test@sample.com", "validation_context"=>nil}

そのため、Formオブジェクトのコンストラクタを下記のように編集します。
ActiveModel::ModelをincludeしたFormオブジェクトは、デフォルトでActiveModel::Modelのinitializeメソッドを使用するため、今回はFormオブジェクト内で特定の属性のみ初期化するinitializeメソッドを定義する必要があるためです。

class UserForm
  include ActiveModel::Model

  attr_accessor :name, :email, :verify_code

  def initialize(attribute = {})
    → @name = attribute['name']
    → @email = attribute['email']
  end
end

以上です!!

今回のサンプルコード

こちらです⤵︎⤵︎

ご拝読ありがとうございました!!m(_ _)m

0
0
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
0
0