Advertisement
  1. Code
  2. Ruby on Rails

Khám phá Devise, Phần 2

Scroll to top
Read Time: 8 min
This post is part of a series called Exploring Devise.
Exploring Devise, Part 1

Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article)

Lời giới thiệu

Trong phần đầu của chủ đề này, chúng ta đã học cách cài đặt Devise và thiết lập nó trong ứng dụng Rails của chúng ta. Trong phần này, chúng ta sẽ tìm hiểu cách tích hợp DeviseInvitable.

DeviseInvitable là một phần mở rộng hoạt động cùng với Devise. Với DeviseInvitable trong ứng dụng của bạn, người dùng của bạn có thể mời bạn bè của họ thông qua email. Đây là một tính năng tuyệt vời để thêm vào trong ứng dụng của bạn nếu bạn đang xây dựng một ứng dụng cộng tác.

Thiết lập DeviseInvitable

Mở Gemfile của bạn và thêm gem vào:

1
#Gemfile
2
...
3
gem 'devise_invitable'

Chạy lệnh để cài đặt bundle bundle install.

Chạy lệnh generate để thêm tùy chọn cấu hình DeviseInvitable vào tập tin cấu hình Devise.

1
rails generate devise_invitable:install

Bạn có thể thấy những thay đổi mới bằng cách kiểm tra tập tin config/initializers/devise.rb với trình soạn thảo văn bản của bạn.

Tiếp theo, hãy thêm DeviseInvitable vào model User của bạn.

1
rails generate devise_invitable User

Điều này sẽ thêm cờ :invitable vào model của bạn, do đó model User của bạn sẽ trông giống như cái này:

1
#app/models/user.rb
2
3
class User < ActiveRecord::Base
4
  # Include default devise modules. Others available are:
5
  # :confirmable, :lockable, :timeoutable and :omniauthable
6
  devise :invitable, :database_authenticatable, :registerable,
7
         :recoverable, :rememberable, :trackable, :validatable
8
end

Chạy lệnh ở trên cũng tạo ra một tập tin di trú mà trông giống như những gì tôi có dưới đây:

1
class DeviseInvitableAddToUsers < ActiveRecord::Migration
2
  def up
3
    change_table :users do |t|
4
      t.string     :invitation_token
5
      t.datetime   :invitation_created_at
6
      t.datetime   :invitation_sent_at
7
      t.datetime   :invitation_accepted_at
8
      t.integer    :invitation_limit
9
      t.references :invited_by, polymorphic: true
10
      t.integer    :invitations_count, default: 0
11
      t.index      :invitations_count
12
      t.index      :invitation_token, unique: true # for invitable
13
      t.index      :invited_by_id
14
    end
15
  end
16
17
  def down
18
    change_table :users do |t|
19
      t.remove_references :invited_by, polymorphic: true
20
      t.remove :invitations_count, :invitation_limit, :invitation_sent_at, :invitation_accepted_at, :invitation_token, :invitation_created_at
21
    end
22
  end
23
end

Bây giờ di chuyển cơ sở dữ liệu của bạn bằng cách chạy rake db:migrate.

Cấu hình Controller cho DeviseInvitable

DeviseInvitable yêu cầu được truyền một số tham số khi gửi một lời mời. Để điều này hoạt động, chúng ta cần phải tạo một danh sách trắng với các tham số cần thiết sẽ được sử dụng. Sử dụng trình soạn thảo văn bản của bạn, mở tập tin app/controllers/application_controller.rb và làm cho nó trông giống những gì mà tôi có ở dưới:

1
#app/controllers/application_controller.rb
2
3
class ApplicationController < ActionController::Base
4
  # Prevent CSRF attacks by raising an exception.
5
  # For APIs, you may want to use :null_session instead.
6
  protect_from_forgery with: :exception
7
8
  before_action :configure_permitted_parameters, if: :devise_controller?
9
10
  protected
11
12
  def configure_permitted_parameters
13
    added_attrs = [:username, :email, :password, :password_confirmation, :remember_me]
14
    devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
15
    devise_parameter_sanitizer.permit :account_update, keys: added_attrs
16
    devise_parameter_sanitizer.permit :accept_invitation, keys: [:email]
17
  end
18
end

Từ ở trên, bạn có thể thấy rằng :email đã được đưa vào danh sách trắng cho DeviseInvitable.

Bây giờ chúng ta hãy xem những gì chúng ta có thông qua giao diện dòng lệnh của chúng ta. Trên terminal của bạn, chạy rails console và nhập những gì bạn có dưới đây.

1
[1] pry(main)> User.invite!(:email => "johndoe@example.com")

Nó sẽ tạo ra những thứ trông giống như những gì tôi có dưới đây, mặc dù sẽ có thể có sự khác biệt.

1
[2] pry(main)> User Load (78.3ms)  SELECT  "users".* FROM "users" WHERE "users"."email" = ?  ORDER BY "users"."id" ASC LIMIT 1  [["email", "johndoe@example.com"]]
2
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."invitation_token" = ?  ORDER BY "users"."id" ASC LIMIT 1  [["invitation_token", "658da470d5fcbb2275f30bc1fb66f5771b889cec2f1e56f536319d2fd1ef4a92"]]
3
   (0.1ms)  begin transaction
4
  SQL (67.8ms)  INSERT INTO "users" ("email", "encrypted_password", "invitation_token", "invitation_created_at", "invitation_sent_at", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?)  [["email", "johndoe@example.com"], ["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"]]
5
   (220.5ms)  commit transaction
6
  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)
7
  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)
8
9
Devise::Mailer#invitation_instructions: processed outbound mail in 247.1ms
10
11
Sent mail to johndoe@example.com (74.3ms)
12
Date: Fri, 07 Oct 2016 08:41:51 +0100
13
From: please-change-me-at-config-initializers-devise@example.com
14
Reply-To: please-change-me-at-config-initializers-devise@example.com
15
To: johndoe@example.com
16
Message-ID: <57f751bfce8d6_18022ac6c272b12840661@kinsomicrote-X553MA.mail>
17
Subject: Invitation instructions
18
Mime-Version: 1.0
19
Content-Type: multipart/alternative;
20
 boundary="--==_mimepart_57f751bfcc725_18022ac6c272b12840524";
21
 charset=UTF-8
22
Content-Transfer-Encoding: 7bit
23
24
25
----==_mimepart_57f751bfcc725_18022ac6c272b12840524
26
Content-Type: text/plain;
27
 charset=UTF-8
28
Content-Transfer-Encoding: 7bit
29
30
Hello johndoe@example.com
31
32
Someone has invited you to https://localhost:3000/, you can accept it through the link below.
33
34
http://localhost:3000/users/invitation/accept?invitation_token=xmW9uRfyafptmeFMmFBy
35
36
37
If you don't want to accept the invitation, please ignore this email.

38
Your account won't be created until you access the link above and set your password.
39
40
----==_mimepart_57f751bfcc725_18022ac6c272b12840524
41
Content-Type: text/html;
42
 charset=UTF-8
43
Content-Transfer-Encoding: 7bit
44
45
<p>Hello johndoe@example.com</p>
46
47
<p>Someone has invited you to http://localhost:3000/, you can accept it through the link below.</p>
48
49
<p><a href="http://localhost:3000/users/invitation/accept?invitation_token=xmW9uRfyafptmeFMmFBy">Accept invitation</a></p>
50
51
52
<p>If you don't want to accept the invitation, please ignore this email.<br />

53
Your account won't be created until you access the link above and set your password.</p>
54
55
----==_mimepart_57f751bfcc725_18022ac6c272b12840524--
56
57
=> #<User:0x00558d875fa798

58
 id: 4,
59
 email: "johndoe@example.com",
60
 encrypted_password: "$2a$11$0sLfqvfFDsebcmcQTUXzlOuqNIooL5z8niXeza8OUwNK3gZY/iRum",
61
 reset_password_token: nil,
62
 reset_password_sent_at: nil,
63
 remember_created_at: nil,
64
 sign_in_count: 0,
65
 current_sign_in_at: nil,
66
 last_sign_in_at: nil,
67
 current_sign_in_ip: nil,
68
 last_sign_in_ip: nil,
69
 created_at: Fri, 07 Oct 2016 07:41:51 UTC +00:00,
70
 updated_at: Fri, 07 Oct 2016 07:41:51 UTC +00:00,
71
 username: nil,
72
 invitation_token: "658da470d5fcbb2275f30bc1fb66f5771b889cec2f1e56f536319d2fd1ef4a92",
73
 invitation_created_at: Fri, 07 Oct 2016 07:41:51 UTC +00:00,
74
 invitation_sent_at: Fri, 07 Oct 2016 07:41:51 UTC +00:00,
75
 invitation_accepted_at: nil,
76
 invitation_limit: nil,
77
 invited_by_id: nil,
78
 invited_by_type: nil,
79
 invitations_count: 0>
80
[3] pry(main)> 

Nó hoạt động như đã định.

Bạn không muốn người dùng của bạn gửi thư mời thông qua giao diện dòng lệnh, do đó, quan trọng là chúng ta thiết lập DeviseInvitable để nó hoạt động ở front end. Thực hiện điều này là rất đơn giản; chạy lệnh generate để tạo ra các view cho DeviseInvitable.

rails generate devise_invitable:views users

Bạn cũng sẽ cần phải thêm một liên kết đến một nơi nào đó trong ứng dụng của bạn mà trỏ đến trang gửi lời mời (app/views/users/invitations/new.html.erb).

Đối với ứng dụng này, bạn có thể thêm liên kết trong tập tin navigation của bạn. Dưới đây là cách tôi đã làm:

1
#app/views/shared/_navigation.html.erb
2
3
<nav class="navbar navbar-inverse">
4
  <div class="container">
5
    <div class="navbar-header">
6
      <%= link_to 'Tutsplus Devise', root_path, class: 'navbar-brand' %>
7
    </div>
8
    <div id="navbar">
9
      <ul class="nav navbar-nav">
10
        <li><%= link_to 'Home', root_path %></li>
11
      </ul>
12
      <ul class="nav navbar-nav pull-right">
13
        <% if user_signed_in? %>
14
          <li class="dropdown">
15
            <a class="dropdown-toggle" data-toggle="dropdown" href="#">
16
              <%= current_user.username %>
17
              <span class="caret"></span>
18
            </a>
19
            <ul class="dropdown-menu" role="menu">
20
              <li><%= link_to 'Invite', new_user_invitation_path %></li>
21
              <li><%= link_to 'Profile', edit_user_registration_path %></li>
22
              <li><%= link_to 'Log out', destroy_user_session_path, method: :delete %></li>
23
            </ul>
24
          </li>
25
        <% else %>
26
          <li><%= link_to 'Log In', new_user_session_path %></li>
27
          <li><%= link_to 'Sign Up', new_user_registration_path %></li>
28
        <% end %>
29
      </ul>
30
    </div>
31
  </div>
32
</nav>

Để xem các route được tạo ra bởi DeviseInvitable, chạy lệnh rake routes | invit. Dưới đây là những gì mà nó xuất ra.

1
cancel_user_registration GET    /users/cancel(.:format)            devise_invitable/registrations#cancel
2
       user_registration POST   /users(.:format)                   devise_invitable/registrations#create
3
   new_user_registration GET    /users/sign_up(.:format)           devise_invitable/registrations#new
4
  edit_user_registration GET    /users/edit(.:format)              devise_invitable/registrations#edit
5
                         PATCH  /users(.:format)                   devise_invitable/registrations#update
6
                         PUT    /users(.:format)                   devise_invitable/registrations#update
7
                         DELETE /users(.:format)                   devise_invitable/registrations#destroy
8
  accept_user_invitation GET    /users/invitation/accept(.:format) devise/invitations#edit
9
  remove_user_invitation GET    /users/invitation/remove(.:format) devise/invitations#destroy
10
         user_invitation POST   /users/invitation(.:format)        devise/invitations#create
11
     new_user_invitation GET    /users/invitation/new(.:format)    devise/invitations#new
12
                         PATCH  /users/invitation(.:format)        devise/invitations#update
13
                         PUT    /users/invitation(.:format)        devise/invitations#update

Chúng ta hãy xem những gì chúng ta có tại thời điểm này. Chạy lệnh để khởi động server của bạn; rails server.

Mở trình duyệt và truy cập vào http://localhost:3000/users/invitation/new. Nhập địa chỉ email trong form, và nhấp vào nút. Nó sẽ  hoạt động! Nếu bạn truy cập vào tập tin logs của máy chủ của bạn, bạn sẽ thấy một đầu ra đã được tạo khi bạn gửi lời mời. Tại đầu ra, bạn sẽ thấy một liên kết để chấp nhận lời mời.

Bạn sẽ đồng ý với tôi là nó sẽ tốt hơn nếu bạn có thể xem email được gửi trong trình duyệt của bạn. Chúng ta hãy xem làm thế nào để điều đó hoạt động được.

Tích hợp Letter_Opener

Letter Opener cho phép bạn xem trước các email trong trình duyệt mặc định của bạn. Với nó, bạn không phải thiết lập một hệ thống gởi thư khi làm việc trong môi trường phát triển.

Mở Gemfile của bạn và thêm gem dưới đây:

gem 'letter_opener'

Chạy bundle install.

Sử dụng trình soạn thảo văn bản của bạn, điều hướng đến config/environments/development.rb và thêm dòng code sau:

1
#config/environments/development.rb
2
...
3
  config.action_mailer.delivery_method = :letter_opener
4
end

Khởi động lại rails server của bạn. Truy cập đến http://localhost:3000/users/invitation/new. Điền và gởi form hiển thị trong đó. Lần này, một trang mới sẽ bật lên có chứa email lời mời.

Thay đổi các Route Đăng nhập và Đăng xuất mặc định

Mặc định, các route sign_insign_out khi sử dụng Devise trông giống như thế này:

sign_inhttp://localhost:3000/users/sign_in

sign_outhttp://localhost:3000/users/sign_out

Để thay đổi nó, hãy vào config/routes.rb và thêm những thứ sau đây:

1
#config/routes.rb
2
  as :user do
3
    get 'signin' => 'devise/sessions#new'
4
    post 'signin' => 'devise/sessions#create'
5
    delete 'signout' => 'devise/sessions#destroy'
6
  end

Bạn có thể truy cập http://localhost:3000/signin.

Kết luận

Bây giờ bạn biết cách tận dụng DeviseInvitable. Bạn cũng đã tìm hiểu về gem letter_opener. Có rất nhiều thứ bạn có thể làm với Devise, vì vậy hãy kiểm tra Wiki để tìm hiểu thêm. Cảm ơn bạn đã theo dõi.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.