Custom Validators of devise in Ruby on Rails 4
1. Thế nào là validation? Sau khi người dùng submit dữ liệu từ client lên server thì các validation mặc định sẽ hoạt động nhằm thông báo cho người dùng đã nhập đúng hay chưa. Ví dụ, khi ta dùng gem 'devise' để authenticate thì khi người dùng không nhập gì cả mà bấm nút login thì sẽ xuất hiện ra ...
1. Thế nào là validation?
Sau khi người dùng submit dữ liệu từ client lên server thì các validation mặc định sẽ hoạt động nhằm thông báo cho người dùng đã nhập đúng hay chưa. Ví dụ, khi ta dùng gem 'devise' để authenticate thì khi người dùng không nhập gì cả mà bấm nút login thì sẽ xuất hiện ra 2 thông báo: "chưa nhập email" và "chưa nhập mật khẩu". Nhưng bây giờ chúng ta chỉ muốn xuất ra 1 thông báo và nội dung thông báo lỗi theo mong muốn như hình ảnh bên dưới thì phải làm thế nào?
Để được message thông báo như trên chúng ta phải custom các validations mặc định. Cụ thể ở đây chúng ta sẽ custom validation của gem 'divise'
2. Cách custom validators
Thông thường khi khai báo devise cho model nào đó thì model đấy sẽ trông như thế này:
# app/models/user.rb class User < ActiveRecord::Base devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable # Khi muốn custom validation thì ta phải bỏ thuộc tính này #... end
Ta thấy một thuộc tính :validatable của gem devise, chính thuộc tính này sẽ mặc định validate các form của hệ thống đăng nhập khi được bấm nút submit or login. Vậy ta muốn custom nó trước hết ta hãy xóa thuộc tính này đi và tạo một file validator nằm trong thư mục app/validators/:
#app/validators/login_validator.rb class LoginValidator < ActiveModel::Validator VALID_EMAIL_REGEX = /A[w+-.]+@[a-zd-]+(.[a-z]+)*.[a-z]+z/i def validate record if record.email.blank? && record.encrypted_password.blank? record.errors[:メールアドレスとパスワード] << " を入力してください。" elsif record.encrypted_password.blank? record.errors[:パスワード] << " を入力してください。" elsif record.email.blank? record.errors[:メールアドレス] << " を入力してください。" elsif record.email.present? && record.email !~ VALID_EMAIL_REGEX record.errors[:メール形式] << " が正しくありません。" else resource = record.class.find_by email: record.email, encrypted_password: record.encrypted_password if resource.blank? record.errors[:メールアドレスまたはパスワード] << " が正しくありません。" end end end end
Để tạo thư mục này có thể được nạp đạn tự động khi khởi động, chúng ta cần phải thêm nó vào config/application.rb
# config/application.rb # ... # add custom validators path config.autoload_paths += %W["#{config.root}/app/validators/"] # ...
Vậy sau khi tao ra được file login_validator.rb cho devise, một câu hỏi đặt ra là gọi login_validator.rb này ở đâu? Chúng ta sẽ tạo ra một class controller SessionsController được kế thừa từ Devise::SessionsController
#app/controllers/sessions_controller.rb class SessionsController < Devise::SessionsController def new if user_signed_in? redirect_to root_path else self.resource = resource_class.new(sign_in_params) # Chúng ta sẽ gọi LoginValidator ở đây resource.validates_with(LoginValidator) unless sign_in_params.empty? clean_up_passwords(resource) yield resource if block_given? respond_with(resource, serialize_options(resource)) end end end
=> Như vậy chúng ta đã custom được validator của gem 'devise' khi thực hiện chức năng login
3. Kết luận
Qua ví dụ mẫu ở trên ta có thể thấy rằng việc thực hiện custom validation của gem 'devise' khá là dễ dàng và gọn nhẹ. Tương tự như việc custom validation của 'devise' chúng ta có thể sử dụng phương pháp này cho nhiều các model khác với nhiều chức năng như thêm, sửa, xóa... chúng ta có thể tùy biến được số lượng message và nội dung các lỗi được phát hiện khi thực các chức năng nào đó của các model.