Form Objects Pattern in Rails
Khi bạn có một form phức tạp, một form phải xử lý 2,3, thậm chí nhiều object một lúc. Bạn sẽ làm như thế nào? Đối với tôi, thì tôi thường hay sử dụng Form Objects. Vậy tại sao lại dùng Form Object, và dùng nó như thế nào? thì bài viết hôm nay tôi sẽ đề cập đến điều này Tại sao lại sử dụng Form ...
Khi bạn có một form phức tạp, một form phải xử lý 2,3, thậm chí nhiều object một lúc. Bạn sẽ làm như thế nào? Đối với tôi, thì tôi thường hay sử dụng Form Objects. Vậy tại sao lại dùng Form Object, và dùng nó như thế nào? thì bài viết hôm nay tôi sẽ đề cập đến điều này
Tại sao lại sử dụng Form Objects?
Bạn đã bao giờ nghe đến fat models? Fat models là gì? Nó muốn nói về vấn đề, một model của bạn phải thực hiện quá nhiều nhiệm vụ, cả việc authentication và accepting attributes cho các model khác, dẫn đến tình trạng nó quá lớn. Và khi đó, model sẽ vi phạm một quy tắc rất phổ biến đó là the single responsibility principle.
The single responsibility principle states that every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class.
Và đó là vấn đề của bài toán mà chúng ta đã đưa ra xử lý một form phức tạp. Và chúng ta giải quyết nó bằng Form Objects Pattern.
Tiếp theo, chúng ta sẽ cùng ứng Form objects trong một bài toán cụ thể.
Form Objects Pattern
1. Bài toán.
Chúng ta có một form để người dùng đăng kí sử dụng hệ thống của mình. Và ở trong đó, chúng ta yêu cầu người dùng nhập những thông tin cơ bản như: email, first_name, last_name, ngoài ra chúng ta còn yêu cầu người dùng nhập thông tin của company của họ như tên cty, địa chỉ. Đồng thời thông báo cho admin của hệ thống biết về thông tin của người dùng đã đăng kí. Rõ ràng ở đây, chúng ta cần xử lý lưu thông tin của 2 đối tượng cùng một lúc đó là: user và company, và thực hiện hành động gửi thông báo.
Chúng ta sẽ sử dụng Form objects pattern cho bài toán này.
2. Form objects.
Bước đầu tiên, chúng ta sẽ tạo một Object cho form register, như sau:
#app/forms/registration.rb class Registration include ActiveModel::Model attr_accessor :company_name, :company_address, :email, :first_name, :last_name validates :company_name, presence: true validates :company_address, presence: true validates :email, presence: true, email: true validates :first_name, presence: true validates :last_name, presence: true def save if valid? # Do something # - create company # - create user # - send notifications true else false end end private def create_company # handle create a company end def create_user # handle create a company end def sent_notifications # sent notifications to admin end end
Ở đây, chúng ta thực hiện validations cho các thuộc tính như bình thường. Đồng thời viết thêm method save tương tự như method save mặc định của ActiveRecord, để thực hiện những action mà chúng ta cần thực hiện như: tạo company, tạo user, gửi thông báo.
Tiếp theo, thật quen thuộc, chúng ta sẽ thực hiện những gì giống như một form bình thường của Rails.
Tạo controller và views tương ứng thôi nào.
# app/controllers/registration_controller.rb class RegistrationsController < ApplicationController def new @registration = Registration.new end def create @registration = Registration.new registration_params if @registration.save # do something else render :new end end private def registration_params params.require(:registration).permit :company_name, :company_address, :email, :first_name, :last_name end end
# app/views/registration/new.html.erb <%= form_for @registration do |f| %> <%= f.label :company_name, t(".company_name") %>: <%= f.text_field :first_name %> ... <%= f.submit %> <% end %>
Nhìn nó thật quen thuộc đúng ko