When creating a login function etc. using a Gem called devise of Rails I think there are times when you want to separate the login screen and management between the general public and the company.
I've used devise to create web applications, This is the first time I have implemented it on multiple models, so I would like to keep it as a memorandum.
environment
Ruby: 2.5.6
Rails: 5.2.4
devise: 4.7.3
Since I work in docker, it has bundle exec
,
If you are outside docker, please remove it and enter it.
I also wanted to do Facebook authentication this time, so I added devise
and omniauth-twitter
to the Gemfile
Gemfile
gem 'devise'
gem 'omniauth-facebook'
And bundle install
Enter the following command in the terminal
bundle exec rails g devise:install
I think the following words will come out
create config/initializers/devise.rb
create config/locales/devise.en.yml
===============================================================================
Depending on your application's configuration some manual setup may be required:
1. Ensure you have defined default url options in your environments files. Here
is an example of default_url_options appropriate for a development environment
in config/environments/development.rb:
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
In production, :host should be set to the actual host of your application.
* Required for all applications. *
2. Ensure you have defined root_url to *something* in your config/routes.rb.
For example:
root to: "home#index"
* Not required for API-only Applications *
3. Ensure you have flash messages in app/views/layouts/application.html.erb.
For example:
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
* Not required for API-only Applications *
4. You can copy Devise views (for customization) to your app by running:
rails g devise:views
* Not required *
===============================================================================
Check the contents of each and add them.
config / environments / development.rb
.
As I was told, I will list the default URL.config/environments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
config / routes.rb
as root (when accessing the URL set in 1)
I haven't created it yet, so I'll create it here.Terminal
bundle exec rails g controller Posts(Controller name) index
Set the URL in config / routes.rb
config/routes.rb
Rails.application.routes.draw do
root 'posts#index'
end
app / views / layouts / application.html.erb
I wrote what is described for the time being.ruby:app/views/layouts/application.html.erb
.
.
.
<body>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
</html>
Change the setting of config / initializers / devise.rb
to make the login user 2 patterns.
It was originally commented out so please look for it!
config/initializers/devise.rb(Change before)
.
#config.scoped_views = false
.
.
#config.sign_out_all_scopes = true
.
config/initializers/devise.rb(After change)
#Changed to separate login screens for multiple models
config.scoped_views = true
#Prevents logging out of one when logging out of the other when logging in with multiple models
config.sign_out_all_scopes = false
This time, I will make two patterns, one for the general public and one for the company!
Terminal
bundle exec rails g devise user
bundle exec rails g devise company
(Since the same file other than the model name is generated, the company model file is omitted.)
db/migrate/20201112105533_devise_create_users.rb
# frozen_string_literal: true
class DeviseCreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.string :current_sign_in_ip
# t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
Added : omniauthable
andomniauth_providers: [: facebook]
to incorporate Facebook authentication.
models/user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:facebook]
end
Bundle exec rails db: migrate
where you can make changes and additions
config/routes.rb
Rails.application.routes.draw do
devise_for :companies
devise_for :users
root 'postss#index'
end
The Controller # Action part is the same for company and user. In other words, the controllers are the same and need to be changed. (* Only Controller # Action has left ... It's annoying and I can't fix it, so slide it to the right ...! )
Terminal
Prefix Verb URI Pattern Controller#Action
new_company_session GET /companies/sign_in(.:format) devise/sessions#new
company_session POST /companies/sign_in(.:format) devise/sessions#create
destroy_company_session DELETE /companies/sign_out(.:format) devise/sessions#destroy
new_company_password GET /companies/password/new(.:format) devise/passwords#new
edit_company_password GET /companies/password/edit(.:format) devise/passwords#edit
company_password PATCH /companies/password(.:format) devise/passwords#update
PUT /companies/password(.:format) devise/passwords#update
POST /companies/password(.:format) devise/passwords#create
cancel_company_registration GET /companies/cancel(.:format) devise/registrations#cancel
new_company_registration GET /companies/sign_up(.:format) devise/registrations#new
edit_company_registration GET /companies/edit(.:format) devise/registrations#edit
company_registration PATCH /companies(.:format) devise/registrations#update
PUT /companies(.:format) devise/registrations#update
DELETE /companies(.:format) devise/registrations#destroy
POST /companies(.:format) devise/registrations#create
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_facebook_omniauth_authorize GET|POST /users/auth/facebook(.:format) devise/omniauth_callbacks#passthru
user_facebook_omniauth_callback GET|POST /users/auth/facebook/callback(.:format) devise/omniauth_callbacks#facebook
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
user_password PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
POST /users/password(.:format) devise/passwords#create
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
user_registration PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
POST /users(.:format) devise/registrations#create
config/routes.rb
devise_for :companies, controllers: {
sessions: 'companies/sessions',
passwords: 'companies/passwords',
registrations: 'companies/registrations'
}
devise_for :users, controllers: {
sessions: 'users/sessions',
passwords: 'users/passwords',
registrations: 'users/registrations',
omniauth_callbacks: 'users/omniauth_callbacks'
}
If you check again with bundle exec rails routes
, the controller part will be changed safely!
This is the part that was not supported when the first rails g devise: install
was executed.
Terminal
bundle exec rails g devise:views users
bundle exec rails g devise:views companies
I think each file was generated!
Terminal
bundle exec rails generate devise:controllers users
bundle exec rails generate devise:controllers companies
I think that the execution result will be like this.
create app/controllers/users/confirmations_controller.rb
create app/controllers/users/passwords_controller.rb
create app/controllers/users/registrations_controller.rb
create app/controllers/users/sessions_controller.rb
create app/controllers/users/unlocks_controller.rb
create app/controllers/users/omniauth_callbacks_controller.rb
===============================================================================
Some setup you must do manually if you haven't yet:
Ensure you have overridden routes for generated controllers in your routes.rb.
For example:
Rails.application.routes.draw do
devise_for :users, controllers: {
sessions: 'users/sessions'
}
end
===============================================================================
The bottom part, a rainy day error! ?? I thought, but it's not an error. (Hot Since the controller looks like this, you need to add the following description to routes.rb ~ I give an example and teach me.
Since it was set earlier, you can ignore it!
At this rate, even if you access http: // localhost: 3000 / users / sign_in
, an error will occur.
Something like undefined method `omniauth_authorize_path'for ~
. ..
I won't go into the Facebook authentication settings here, in app / views / users / shared / _links.html.erb The part of omniauth_authorize_path (resource_name, provider) is strange.
If you check the ruding, there is no path called omniauth_authorize_path
, it should be user_facebook_omniauth_authorize_path
, so let's fix it.
I didn't change the name using as ...? I thought, I wasn't sure why. Is it from the beginning ...?
Anyway! For the time being, the basic setting part is completed.
http: // localhost: 3000 / users / sign_in
and http: // localhost: 3000 / companies / sign_in
Whichever way you access, you will see the login screen!
Add more columns or customize if needed!
I hope this article helps someone. Thank you very much!
Recommended Posts