Quantcast
Channel: CSSタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8925

ユーザー登録(devise)と同時に別モデルにデータを同時保存したい場合の話。

$
0
0
はじめに オンラインスクールにてRuby on Railsの学習をはじめ5ヶ月が経ちました。 リリースを前提に現在開発予定のアプリに実装した機能のアウトプットになります。 「Deviseのユーザー登録と同時に別モデルにデータを保存する方法」です。 具体的なユースケースの例は、下記のような場合です。 ・ユーザー登録と同時に銀行口座が開設される。 ・ユーザーは1つの銀行口座しか持つことができない。 ・銀行口座IDとユーザーIDは紐付く。 ・登録時の口座残高の初期値はnullではなく0円。 ユーザー登録と同時に何か一つ、自動で生成されるモノ。を実装する際はお役に立てるかと思います。 ※今回は、バリデーションについては触れません。 ※今回は、アプリ作成・Devise導入・基本的なユーザー管理機能の説明は省きます。 導入 ユーザー管理機能の実装が終わっている前提。 最低限、ユーザー新規登録とログインはできる状態でこちらをお読み下さい。 まず前提として、deviseは基本的にGemで動くものなので、通常のMVCの流れとは違います。 ”ユーザー登録と同時”に何か”別の動き”をさせるには、少なくともコントローラーに何かしら記述しなければいけません。 すなわち、”Userコントローラー”の”Createアクション”に追加で記述ができればなぁとなります。 しかし、ここで問題です。 私もスクールカリキュラム内で以下の通り学習しました。 「deviseの処理を行うコントローラーはGem内に記述されているため、編集することができません。」 ただ、deviseに使うストロングパラメーターの許可は、全てapplication_controller.rbに記述すれば使えるよ。という事でしたね。 しかし、色々と調べてみると、どうやら、deviseのコントローラの中身を細かくカスタマイズできるらしい。という事がわかったのでまずはそこから説明していきます。 本編 1. Usersコントローラの作成 $ rails g devise:controllers users # => usersコントローラの作成 上記コマンドで、usersコントローラを召喚します。 これを実行すれば、deviseに関係する全てのコントローラー及びアクションを自由に編集する為のコントローラーファイルがすべて作成されます。 2.銀行モデル・テーブルの作成 ユーザー登録時に同時に登録したい銀行口座モデル及び銀行口座テーブルの作成をします。 $ rails g model bank stock_quantity:integer user:references # =>Bankモデルの作成 $ # stock_quantityカラム:銀行残高 # user_idカラム→Userモデルから口座を呼び出す為の外部キー $ rails db:migrate 3.モデル同士のアソシエーション「1対1」を組む app/models/user.rb class User < ApplicationRecord has_one :bank, dependent: :destroy # ユーザーは1つの銀行口座しか開設できない accepts_nested_attributes_for :bank # ここがポイント devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable end Userモデルの「accepts_nested_attributes_for :bank」によって、Userモデルを通して、Bankの値をDBに保存することが出来ます。 app/models/bank.rb class Bank < ApplicationRecord belongs_to :user end 4.application_controller.rbでストロングパラメーターの許可 app/controllers/application_controller.rb class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? def configure_permitted_parameters # 新規登録の時(sign_upアクション)に許可するパラメーター devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :gender_id, :last_name, :first_name, { bank_attributes: [:stock_quantity] }]) end end # { bank_attributes: [:stock_quantity] }に注目 # これでユーザー登録時にBankモデルのパラメータの許可も追加しています。 5.registrations_controller.rbでストロングパラメーターの許可 app/controllers/users/registrations_controller.rb # frozen_string_literal: true class Users::RegistrationsController < Devise::RegistrationsController before_action :configure_sign_up_params, only: [:create] #before_action :configure_account_update_params, only: [:update] # GET /resource/sign_up #def new # super #end # POST /resource def create super @user = User.new(bank_params) @user.build_bank @user.save end # GET /resource/edit #def edit # super #end # PUT /resource #def update # super #end # DELETE /resource #def destroy # super #end # GET /resource/cancel # Forces the session data which is usually expired after sign # in to be expired now. This is useful if the user wants to # cancel oauth signing in/up in the middle of the process, # removing all OAuth session data. #def cancel # super #end # protected # If you have extra params to permit, append them to the sanitizer. def configure_sign_up_params devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute]) end # If you have extra params to permit, append them to the sanitizer. #def configure_account_update_params # devise_parameter_sanitizer.permit(:account_update, keys: [:attribute]) #end # The path used after sign up. def after_sign_up_path_for(resource) super(resource) end # The path used after sign up for inactive accounts. def after_inactive_sign_up_path_for(resource) super(resource) end private def bank_params params.permit(:sign_up, keys: [:nickname, :gender_id, :last_name, :first_name, { bank_attributes: [:stock_quantity] }]) end end ・必要箇所のコメントアウトを削除 ※今回は、新規登録のcreateアクションの箇所のみ。各自、必要なアクションの箇所を消してくださいね。 ・createアクション内に同時保存の追記 「build_bank」は、Userモデルに定義した「has_one :bank」によって、Userモデルのインスタンスメソッドとして使えるようになっているメソッドです。 「@bank = Bank.new」としても、ビューで@userにネストした@bankを参照することができません。 ・一番下、privateメソッド配下にbank_paramsの定義を追加 ※これを忘れると、先程application_contoroller.rbで記述したストロングパラメータの許可が降りません。 6.ルーティング編集 config/routes.rb Rails.application.routes.draw do devise_for :users, controllers: { registrations: 'users/registrations' } root to: 'banks#index' end ユーザー登録時に自前で用意したuserコントローラーを経由してくれるようにする。 7.新規登録のVIEWを編集 app/views/devise/registrations/new.html.erb #form_with @user do |f| 配下(内部)に #省略 # 必ずf.fields_forのヘルパーメソッドを使う <%= f.fields_for :bank, Bank.new do |f| %> <%= f.hidden_field :stock_quantity, value: 0 %> # hidden_fieldがミソ <% end %> ユーザー新規登録のVIEWファイルのform_with内に上記を追加する。 ・この時必ずf.fields_forのヘルパーメソッドを使用する。 ※form_with @user do |f|内にf.field_for :bank do |f|をネストする為。 ・hidden_fieldヘルパーメソッドを使用するのがミソ ※今回の同時登録するBankモデルの情報はユーザー登録時にユーザーに入力させる項目ではないため。 ・銀行口座の残高の初期値は0円の為、value:0とする。 おわりに これで、ユーザー新規登録と同時に銀行口座が開設されます。 開設された口座には、必ず一人のユーザーが紐付きます。 そして、最初は残高0円からスタートします。

Viewing all articles
Browse latest Browse all 8925

Trending Articles