+3

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 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 authenticationaccepting 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à: usercompany, 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 😉 Và cuối cùng thì chúng ta cũng đã đạt được mục đích, form objects chịu trách nhiệm nhận input đầu vào từ form và sau đó đưa nó đi đến từng model để lưu dữ liệu vào DB.

Lời kết

Với Form objects chúng ta đã biết thêm một cách để xứ lý với những form phức tạp, thao tác với nhiều object. Nó sẽ giúp code của chúng ta được tổ chức một cách rõ ràng hơn.

Hãy cho tôi biết suy nghĩ của bạn !

Tham khảo

Link gốc: https://railsviet.com/form-object-pattern-trong-rails

Để thực hiện Form objects một cách dễ dàng hơn, các bạn có thể tham khảo 2 gems này:

Ngoài ra, trong bài viết này tôi có tham khảo một số tài liệu sau:


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.