When I made a copy site of flea market, I had a hard time because I made the structure a little difficult, so I decided to keep it as a record. If you have any suggestions, such as making it more beautiful, please.
--devise is already installed
--The login function in the default state of devise has been implemented.
--Transition from page 1 → page 2 → top page (login)
--There are three tables, ʻusers
profiles`` sending_destinations. --The first page deals with both ʻUser model
and Profile model
in one form.
Column | Type | Options |
---|---|---|
name | string | null: false, unique: true, index:true |
string | null: false, unique: true, index:true | |
password | string | null: false |
Column | Type | Options |
---|---|---|
first_name | string | null: false |
family_name | string | null: false |
first_name_kana | string | null: false |
family_name_kana | string | null: false |
introduction | string | null: true |
year | integer | null: false |
month | integer | null: false |
day | integer | null: false |
Column | Type | Options |
---|---|---|
first_name | string | null :false |
family_name | string | null: false |
first_name_kana | string | null: false |
family_name_kana | string | null: false |
post_code | string | null: false |
prefecture | string | null: false |
city | string | null:false |
house_number | string | null: false |
building_name | string | - |
phone_number | string | unique: true, null: true |
user_id | references | null: false, foreign_key: true |
--Create a ʻusers` controller under devise management
Terminal
$ rails g devise:controllers users
--Set the routing to refer to which controller
routes.rb
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: 'users/registrations' }
root to: 'items#index'
end
--Describe associations in each model of ʻUser,
Profile,
Sending_destination`
user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one :profile
accepts_nested_attributes_for :profile
has_one :sending_destination
end
profile.rb
class Profile < ApplicationRecord
belongs_to :user, optional: true
end
sending_destination.rb
class SendingDestination < ApplicationRecord
belongs_to :user, optional: true
end
ʻOptional: true` is an option that allows the foreign key to be null.
--Write a new action in users / registrations_controller.rb
users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
#abridgement
def new
@user = User.new
@user.build_profile
end
#abridgement
end
--Edit registrations / new.html.haml corresponding to new action
ruby:devise/registrations/new.haml.html
= form_for(@user, url: user_registration_path) do |f|
= render "devise/shared/error_messages", resource: @user
= f.text_field :nickname
= f.email_field :email
= f.password_field :password
= f.password_field :password_confirmation
= f.fields_for :profile do |p|
= p.text_field :family_name
= p.text_field :first_name
= p.text_field :family_name_kana
= p.text_field :first_name_kana
= p.select :year
= p.select :month
= p.select :day
= f.submit "next"
Actually, there are descriptions of div, label, and class, but they are written simply.
We are using fields_for
to handle the two models. I refer to the following articles.
[Rails] How to send values to two models at the same time with devise form (example: User model and Profile model)
[Rails] How to register data to multiple models with one form_for
--Validation check of the information entered on the first page --Have the information entered on page 1 in session --Create an instance to be used for the next address information registration and transition to the relevant page The above three points will be done by the create action.
users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
#abridgement
def create
@user = User.new(sign_up_params)
@user.build_profile(sign_up_params[:profile_attributes])
unless @user.valid?
flash.now[:alert] = @user.errors.full_messages
render :new and return
end
session["devise.regist_data"] = {user: @user.attributes}
session["devise.regist_data"][:user]["password"] = params[:user][:password]
session[:profile_attributes] = sign_up_params[:profile_attributes]
@sending_destination = @user.build_sending_destination
render :new_sending_destination
end
#abridgement
protected
#abridgement
end
Check if the parameter violates validation with the valid?
method.
The function session
that keeps the information on the client side is used so that the information does not disappear even if the page changes.
The data is formatted using the attributes method so that the session holds the information in the form of a hash object. Also, although the password information is included in the params, the password information is not included when the data is formatted by the attributes method. So you need to assign the password to session again.
Create an instance of the sending_destination
model associated with the instance @ user
created this time with build_sending_destination
.
Then render to the view of the new_sending_destination
action that displays the page to register the address information.
--Routing settings for the new_sending_destination
action that displays the address registration page
--Routing settings for the create_sending_destination
action to register an address
routes.rb
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: 'users/registrations' }
devise_scope :user do
get 'sending_destinations', to: 'users/registrations#new_sending_destination'
post 'sending_destinations', to: 'users/registrations#create_sending_destination'
end
root to: 'items#index'
end
--Create the corresponding view file new_sending_destination.html.haml
ruby:devise/registrations/new_sending_destination.html.haml
= form_for @sending_destination do |f|
= render "devise/shared/error_messages", resource: @sending_destination
= f.text_field :family_name
= f.text_field :first_name
= f.text_field :family_name_kana
= f.text_field :first_name_kana
= f.text_field :post_code
= f.text_field :prefecture
= f.text_field :city
= f.text_field :house_number
= f.text_field :building_name
= f.number_field :phone_number
= f.submit "sign up"
--Validation check of the address information entered on the second page --Save as user information together with the information that validation check is completed and the information that was held in session. --Delete session --Log in
users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
#abridgement
def create_sending_destination
@user = User.new(session["devise.regist_data"]["user"])
@profile = @user.build_profile(session[:profile_attributes])
@sending_destination = SendingDestination.new(sending_destination_params)
unless @sending_destination.valid?
flash.now[:alert] = @sending_destination.errors.full_messages
render :new_sending_destination and return
end
@user.build_sending_destination(@sending_destination.attributes)
@user.save
@profile.save
session["devise.regist_data"]["user"].clear
session[:profile_attributes].clear
sign_in(:user, @user)
redirect_to root_path
end
protected
def sending_destination_params
params.require(:sending_destination).permit(
:first_name,
:family_name,
:first_name_kana,
:family_name_kana,
:post_code,
:prefecture, :city,
:house_number,
:building_name,
:phone_number
)
end
end
The information held in session is assigned to each instance of @ user
and @ prfile
.
Check the address information on the second page with valid?
.
Substitute the params sent using build_sending_destination into @ user
that contains the held session. Then save it to the table using the save
method.
Delete session using the clear
method.
Log in with sign_in (: user, @user)
and move to the top page with redirect_to root_path
.
It can be implemented by the above method. By using fields_for
on the first page, I had a lot of trouble assigning to session, but thanks to that, I was able to think about the mechanism etc. firmly. I haven't explained it in detail, but I tried to write an article that also serves as an output, so I hope it will be helpful as much as possible.
Recommended Posts