Clearance เป็นระบบยืนยันตัวตนที่เรียบง่ายใช้ email และ password พัฒนาโดยทีม Thoughtbot มีค่าเริ่มต้นที่มีความคิดเห็น (opinionated defaults) แต่ออกแบบให้ง่ายต่อการ override ระบบได้รับการดูแลอย่างต่อเนื่อง ติดตามได้ที่ GitHub
บทเรียนนี้จะแสดงวิธีผสาน Clearance เข้าแอป Rails โดยใช้แอปย่อย มาเริ่มกัน!
เริ่มต้น
สร้างแอป Rails ใหม่ สำหรับบทเรียนนี้ตั้งชื่อ tutsplus-clearance:
rails new tutsplus-clearance -T
เพิ่ม Bootstrap gem ใน Gemfile:
#Gemfile ... gem 'bootstrap-sass'
ติดตั้ง:
bundle install
แก้ไข application.scss:
#app/assets/stylesheets/application.scss @import 'bootstrap-sprockets'; @import 'bootstrap';
ตั้งค่า Clearance
เพิ่ม Clearance gem ใน Gemfile:
#Gemfile gem 'clearance'
ติดตั้ง:
bundle install
รัน generator ติดตั้ง Clearance:
rails generate clearance:install
จะได้ output ในเทอร์มินัล ประมาณนี้:
create config/initializers/clearance.rb
insert app/controllers/application_controller.rb
create app/models/user.rb
create db/migrate/20161115101323_create_users.rb
*******************************************************************************
Next steps:
1. Configure the mailer to create full URLs in emails:
# config/environments/{development,test}.rb
config.action_mailer.default_url_options = { host: 'localhost:3000' }
In production it should be your app's domain name.
2. Display user session and flashes. For example, in your application layout:
<% if signed_in? %>
Signed in as: <%= current_user.email %>
<%= button_to 'Sign out', sign_out_path, method: :delete %>
<% else %>
<%= link_to 'Sign in', sign_in_path %>
<% end %>
<div id="flash">
<% flash.each do |key, value| %>
<div class="flash <%= key %>"><%= value %></div>
<% end %>
</div>
3. Migrate: rake db:migrate
*******************************************************************************
คำสั่งนี้สร้างไฟล์หลายไฟล์ เช่น clearance.rb ใน config/initializers, โมเดล User และไมเกรชัน:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.timestamps null: false
t.string :email, null: false
t.string :encrypted_password, limit: 128, null: false
t.string :confirmation_token, limit: 128
t.string :remember_token, limit: 128, null: false
end
add_index :users, :email
add_index :users, :remember_token
end
end
ตามขั้นตอน แก้ไข config/environments/development.rb เพิ่มบรรทัดก่อน end:
...
config.action_mailer.default_url_options = { host: 'localhost:3000' }
end
แก้ไข config/initializers/clearance.rb เปลี่ยน sender email:
#config/initializers/clearance.rb Clearance.configure do |config| config.mailer_sender = "reply@example.com" end
สามารถ override ค่าเริ่มต้นได้ด้วยโค้ดนี้:
#config/initializers/clearance.rb
Clearance.configure do |config|
config.allow_sign_up = true
config.cookie_domain = ".example.com"
config.cookie_expiration = lambda { |cookies| 1.year.from_now.utc }
config.cookie_name = "remember_token"
config.cookie_path = "/"
config.routes = true
config.httponly = false
config.mailer_sender = "reply@example.com"
config.password_strategy = Clearance::PasswordStrategies::BCrypt
config.redirect_url = "/"
config.secure_cookie = false
config.sign_in_guards = []
config.user_model = User
end
รัน migration:
rake db:migrate
เพิ่ม action index ใน PagesController:
#app/controllers/pages_controller.rb class PagesController < ApplicationController def index end end
สร้างวิว index:
#app/views/pages/index.html.erb <h1>Tutsplus Clearance</h1> <p>Welcome to our Clearance Page.</p>
แก้ routes:
#config/routes.rb Rails.application.routes.draw do root to: "pages#index" end
สร้าง partial _navigation.html.erb ใน layouts:
#app/views/layouts/_navigation.html.erb
<nav class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<%= link_to 'Tutsplus-Clearance', root_path, class: 'navbar-brand' %>
</div>
<div id="navbar">
<% if signed_in? %>
<ul class="nav navbar-nav">
<li><%= link_to 'Add Page', new_page_path %></li>
</ul>
<% end %>
<ul class="nav navbar-nav pull-right">
<% if signed_in? %>
<li><span><%= current_user.email %></span></li>
<li><%= link_to 'Sign out', sign_out_path, method: :delete %></li>
<% else %>
<li><%= link_to 'Sign in', sign_in_path %></li>
<% end %>
</ul>
</div>
</div>
</nav>
<div class="container">
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>">
<%= value %>
</div>
<% end %>
</div>
จำกัดการเข้าถึง (Restricted Access)
Clearance สามารถจำกัดการเข้าถึงหน้าเฉพาะได้ สร้างวิว new.html.erb ใน app/views/pages:
#app/views/pages/new.html.erb <h1>Restricted Page</h1> <p>This page is restricted to authenticated users, if you can see this it means you are a superstar!</p>
เพิ่ม route:
#config/routes.rb ... resources :pages, only: :new ...
แก้ PagesController ใช้ require_login:
#app/controllers/pages_controller.rb class PagesController < ApplicationController before_action :require_login, only: [:new] def index end def new end end
ลองรันเซิร์ฟเวอร์ ไปที่ https://localhost:3000/pages/new จะ redirect ไปหน้า sign in
Clearance ยังมี routing constraints ควบคุมการเข้าถึง:
#config/routes.rb
Rails.application.routes.draw do
constraints Clearance::Constraints::SignedOut.new do
root to: 'pages#index'
end
constraints Clearance::Constraints::SignedIn.new do
root to: "pages#new", as: :signed_in_root
end
end
โค้ดนี้สร้าง route แยกสำหรับผู้ใช้ที่ล็อกอินแล้ว
Override ค่าเริ่มต้นของ Clearance
Clearance ทำงานหลายอย่างเบื้องหลัง อาจต้องปรับแต่ง ต้องการ override ให้รัน:
rails generate clearance:routes
routes จะกลายเป็น:
#config/routes.rb
Rails.application.routes.draw do
resources :passwords, controller: "clearance/passwords", only: [:create, :new]
resource :session, controller: "clearance/sessions", only: [:create]
resources :users, controller: "clearance/users", only: [:create] do
resource :password, controller: "clearance/passwords", only: [:create, :edit, :update]
end
get "/sign_in" => "clearance/sessions#new", as: "sign_in"
delete "/sign_out" => "clearance/sessions#destroy", as: "sign_out"
get "/sign_up" => "clearance/users#new", as: "sign_up"
root to: "pages#index"
resources :pages, only: :new
end
คำสั่งนี้ตั้ง config.routes เป็น false ใน config/initializers/clearance.rb ใช้ไฟล์ custom ที่เพิ่งสร้าง
สร้าง views เพื่อปรับแต่ง:
rails generate clearance:views
ไฟล์ที่สร้างได้:
app/views/passwords/create.html.erb app/views/passwords/edit.html.erb app/views/passwords/new.html.erb app/views/sessions/_form.html.erb app/views/sessions/new.html.erb app/views/users/_form.html.erb app/views/users/new.html.erb config/locales/clearance.en.yml
จะมี prompt ถาม overwrite app/views/layouts/application.html.erb เลือกตามต้องการ
Layouts
Clearance ใช้ layout เริ่มต้นของแอป ถ้าอยากเปลี่ยน ให้ระบุใน initializer:
Clearance::PasswordsController.layout "my_passwords_layout" Clearance::SessionsController.layout "my_sessions_layout" Clearance::UsersController.layout "my_admin_layout"
Helper Methods
Clearance มี helper methods ใช้ใน controllers, views, helpers ได้แก่ signed_in?, signed_out?, current_user ตัวอย่าง:
<% if signed_in? %> <%= current_user.email %> <%= button_to "Sign out", sign_out_path, method: :delete %> <% else %> <%= link_to "Sign in", sign_in_path %> <% end %>
สรุป
Clearance มีฟีเจอร์มากมายสำหรับ authentication ลองใช้ในโปรเจกต์ถัดไป ดูรายละเอียดเพิ่มได้ที่ GitHub