Вступление
В первой части руководства мы узнали, как установить Devise и настроить его в нашем приложении Rails. В этой части мы рассмотрим, как интегрировать DeviseInvitable.
DeviseInvitable — это расширение, которое работает с Devise. С DeviseInvitable в вашем приложении ваши пользователи могут приглашать своих друзей по электронной почте. Это отличная возможность для включения в ваше приложение, если вы создаете приложение для совместной работы.
Настройка DeviseInvitable
Откройте свой Gemfile
и добавьте его:
1
2
3
|
#Gemfile
…
gem ‘devise_invitable’
|
Запустите команду для установки bundle install
.
Запустите команду генератора, чтобы добавить опцию конфигурации DeviseInvitable в файл конфигурации Devise.
1
|
rails generate devise_invitable:install
|
Вы можете увидеть новые изменения, проверив config/initializers/devise.rb
вашем текстовом редакторе.
Далее, давайте добавим DeviseInvitable к нашей модели User
.
1
|
rails generate devise_invitable User
|
Это добавит флаг :invitable
к вашей модели, поэтому ваша модель User будет выглядеть так:
1
2
3
4
5
6
7
8
|
#app/models/user.rb
class User < ActiveRecord::Base
# Include default devise modules.
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
|
Выполнение вышеуказанной команды также сгенерировало файл миграции, который выглядит так, как показано ниже:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class DeviseInvitableAddToUsers < ActiveRecord::Migration
def up
change_table :users do |t|
t.string :invitation_token
t.datetime :invitation_created_at
t.datetime :invitation_sent_at
t.datetime :invitation_accepted_at
t.integer :invitation_limit
t.references :invited_by, polymorphic: true
t.integer :invitations_count, default: 0
t.index :invitations_count
t.index :invitation_token, unique: true # for invitable
t.index :invited_by_id
end
end
def down
change_table :users do |t|
t.remove_references :invited_by, polymorphic: true
t.remove :invitations_count, :invitation_limit, :invitation_sent_at, :invitation_accepted_at, :invitation_token, :invitation_created_at
end
end
end
|
Теперь перенесите вашу базу данных, запустив rake db:migrate
.
Конфигурирование контроллера для DeviseInvitable
DeviseInvitable необходимо передать некоторые параметры при отправке приглашения. Чтобы это работало, нам нужно внести в белый список необходимый параметр, который будет использоваться. Используя ваш текстовый редактор, перейдите в app/controllers/application_controller.rb
и сделайте так, как показано ниже:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
added_attrs = [:username, :email, :password, :password_confirmation, :remember_me]
devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
devise_parameter_sanitizer.permit :account_update, keys: added_attrs
devise_parameter_sanitizer.permit :accept_invitation, keys: [:email]
end
end
|
Из вышесказанного видно, что :email
была добавлена в белый список для DeviseInvitable.
Теперь давайте посмотрим, что мы имеем через нашу консоль. На вашем терминале запустите rails console
и введите то, что у вас ниже.
1
|
[1] pry(main)> User.invite!(:email => «[email protected]»)
|
Он должен произвести вывод, который выглядит так, как у меня ниже, хотя будут различия.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
[2] pry(main)> User Load (78.3ms) SELECT «users».* FROM «users» WHERE «users».»email» = ?
User Load (0.2ms) SELECT «users».* FROM «users» WHERE «users».»invitation_token» = ?
(0.1ms) begin transaction
SQL (67.8ms) INSERT INTO «users» («email», «encrypted_password», «invitation_token», «invitation_created_at», «invitation_sent_at», «created_at», «updated_at») VALUES (?, ?, ?, ?, ?, ?, ?) [[«email», «[email protected]»], [«encrypted_password», «$2a$11$0sLfqvfFDsebcmcQTUXzlOuqNIooL5z8niXeza8OUwNK3gZY/iRum»], [«invitation_token», «658da470d5fcbb2275f30bc1fb66f5771b889cec2f1e56f536319d2fd1ef4a92»], [«invitation_created_at», «2016-10-07 07:41:51.254047»], [«invitation_sent_at», «2016-10-07 07:41:51.254047»], [«created_at», «2016-10-07 07:41:51.255700»], [«updated_at», «2016-10-07 07:41:51.255700»]]
(220.5ms) commit transaction
Rendered /home/kinsomicrote/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/devise_invitable-1.7.0/app/views/devise/mailer/invitation_instructions.html.erb (2.5ms)
Rendered /home/kinsomicrote/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/devise_invitable-1.7.0/app/views/devise/mailer/invitation_instructions.text.erb (88.0ms)
Devise::Mailer#invitation_instructions: processed outbound mail in 247.1ms
Sent mail to [email protected] (74.3ms)
Date: Fri, 07 Oct 2016 08:41:51 +0100
From: [email protected]
Reply-To: [email protected]
Message-ID: <[email protected]>
Subject: Invitation instructions
Mime-Version: 1.0
Content-Type: multipart/alternative;
boundary=»—==_mimepart_57f751bfcc725_18022ac6c272b12840524″;
charset=UTF-8
Content-Transfer-Encoding: 7bit
—-==_mimepart_57f751bfcc725_18022ac6c272b12840524
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 7bit
Hello [email protected]
Someone has invited you to https://localhost:3000/, you can accept it through the link below.
http://localhost:3000/users/invitation/accept?invitation_token=xmW9uRfyafptmeFMmFBy
If you don’t want to accept the invitation, please ignore this email.
Your account won’t be created until you access the link above and set your password.
—-==_mimepart_57f751bfcc725_18022ac6c272b12840524
Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: 7bit
<p>Hello [email protected]</p>
<p>Someone has invited you to http://localhost:3000/, you can accept it through the link below.</p>
<p><a href=»http://localhost:3000/users/invitation/accept?invitation_token=xmW9uRfyafptmeFMmFBy»>Accept invitation</a></p>
<p>If you don’t want to accept the invitation, please ignore this email.<br />
Your account won’t be created until you access the link above and set your password.</p>
—-==_mimepart_57f751bfcc725_18022ac6c272b12840524—
=> #<User:0x00558d875fa798
id: 4,
email: «[email protected]»,
encrypted_password: «$2a$11$0sLfqvfFDsebcmcQTUXzlOuqNIooL5z8niXeza8OUwNK3gZY/iRum»,
reset_password_token: nil,
reset_password_sent_at: nil,
remember_created_at: nil,
sign_in_count: 0,
current_sign_in_at: nil,
last_sign_in_at: nil,
current_sign_in_ip: nil,
last_sign_in_ip: nil,
created_at: Fri, 07 Oct 2016 07:41:51 UTC +00:00,
updated_at: Fri, 07 Oct 2016 07:41:51 UTC +00:00,
username: nil,
invitation_token: «658da470d5fcbb2275f30bc1fb66f5771b889cec2f1e56f536319d2fd1ef4a92»,
invitation_created_at: Fri, 07 Oct 2016 07:41:51 UTC +00:00,
invitation_sent_at: Fri, 07 Oct 2016 07:41:51 UTC +00:00,
invitation_accepted_at: nil,
invitation_limit: nil,
invited_by_id: nil,
invited_by_type: nil,
invitations_count: 0>
[3] pry(main)>
|
Это сработало, как и планировалось.
Вы не хотите, чтобы наши пользователи отправляли приглашения через командную строку, поэтому важно, чтобы мы настроили DeviseInvitable для работы с интерфейсом. Делать это очень просто; выполните команду генератора, чтобы сгенерировать представления для DeviseInvitable.
rails generate devise_invitable:views users
Вам также необходимо добавить ссылку где-нибудь в вашем приложении, которая указывает на страницу для отправки приглашений ( app/views/users/invitations/new.html.erb
).
Для этого приложения вы можете пойти дальше и добавить ссылку на ваш файл навигации. Вот как я это сделал:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#app/views/shared/_navigation.html.erb
<nav class=»navbar navbar-inverse»>
<div class=»container»>
<div class=»navbar-header»>
<%= link_to ‘Tutsplus Devise’, root_path, class: ‘navbar-brand’ %>
</div>
<div id=»navbar»>
<ul class=»nav navbar-nav»>
<li><%= link_to ‘Home’, root_path %></li>
</ul>
<ul class=»nav navbar-nav pull-right»>
<% if user_signed_in?
<li class=»dropdown»>
<a class=»dropdown-toggle» data-toggle=»dropdown» href=»#»>
<%= current_user.username %>
<span class=»caret»>
</a>
<ul class=»dropdown-menu» role=»menu»>
<li><%= link_to ‘Invite’, new_user_invitation_path %></li>
<li><%= link_to ‘Profile’, edit_user_registration_path %></li>
<li><%= link_to ‘Log out’, destroy_user_session_path, method: :delete %></li>
</ul>
</li>
<% else %>
<li><%= link_to ‘Log In’, new_user_session_path %></li>
<li><%= link_to ‘Sign Up’, new_user_registration_path %></li>
<% end %>
</ul>
</div>
</div>
</nav>
|
Чтобы увидеть маршруты, предоставляемые DeviseInvitable, выполните команду rake routes | invit
route rake routes | invit
rake routes | invit
Вот как будет выглядеть вывод.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
cancel_user_registration GET /users/cancel(.:format) devise_invitable/registrations#cancel
user_registration POST /users(.:format) devise_invitable/registrations#create
new_user_registration GET /users/sign_up(.:format) devise_invitable/registrations#new
edit_user_registration GET /users/edit(.:format) devise_invitable/registrations#edit
PATCH /users(.:format) devise_invitable/registrations#update
PUT /users(.:format) devise_invitable/registrations#update
DELETE /users(.:format) devise_invitable/registrations#destroy
accept_user_invitation GET /users/invitation/accept(.:format) devise/invitations#edit
remove_user_invitation GET /users/invitation/remove(.:format) devise/invitations#destroy
user_invitation POST /users/invitation(.:format) devise/invitations#create
new_user_invitation GET /users/invitation/new(.:format) devise/invitations#new
PATCH /users/invitation(.:format) devise/invitations#update
PUT /users/invitation(.:format) devise/invitations#update
|
Давайте посмотрим, что мы имеем в данный момент. Запустите команду для запуска вашего сервера; rails server
.
Укажите в браузере http://localhost:3000/users/invitation/new
. Введите адрес электронной почты в показанной форме и нажмите на кнопку. Это должно работать! Если вы зайдете в журналы вашего сервера, вы должны увидеть выходные данные, которые были созданы при отправке приглашения. В выводе вы увидите ссылку для принятия приглашения.
Вы согласитесь со мной, что будет лучше, если вы сможете просмотреть письмо, отправленное в вашем браузере. Давайте посмотрим, как заставить это работать.
Интеграция Letter_Opener
Letter Opener позволяет просматривать сообщения электронной почты в браузере по умолчанию. При этом вам не нужно настраивать систему доставки почты при работе в среде разработки.
Откройте свой Gemfile и добавьте камень ниже:
gem 'letter_opener'
Запустите bundle install
.
Используя ваш текстовый редактор, перейдите к config/environments/development.rb
и добавьте строку ниже.
1
2
3
4
|
#config/environments/development.rb
…
config.action_mailer.delivery_method = :letter_opener
end
|
Перезагрузите сервер rails. Теперь укажите вашему браузеру http://localhost:3000/users/invitation/new
. Заполните и отправьте форму, отображаемую. На этот раз всплывает новая страница с приглашением.
Изменить маршруты входа и выхода по умолчанию
По умолчанию маршруты sign_in
и sign_out
при использовании Devise выглядят так:
sign_in:
http://localhost:3000/users/sign_in
sign_out:
http://localhost:3000/users/sign_out
Чтобы изменить его, перейдите в config/routes.rb
и добавьте следующее:
1
2
3
4
5
6
|
#config/routes.rb
as :user do
get ‘signin’ => ‘devise/sessions#new’
post ‘signin’ => ‘devise/sessions#create’
delete ‘signout’ => ‘devise/sessions#destroy’
end
|
Вы можете указать свой браузер на http://localhost:3000/signin
.
Вывод
Теперь вы знаете, как использовать DeviseInvitable. Вы также узнали о самоцвете letter_opener
. Есть много вещей, которые вы можете сделать с Devise, так что загляните в Wiki, чтобы узнать больше. Спасибо, что остаетесь со мной.