14/09/2018, 21:14

Phân biệt form_for, form_tag và form_with trong Rails

Trong các phiên bản từ Rails 5.1 trở về trước, form_tag và form_for chắc hẳn đã rất quen thuộc với nhiều người. Nhưng chúng không còn được sử dụng nhiều và sẽ dần bị thay thế bởi form_with (Rails 5.1) trong tương lai. Dưới đây, là một số sự khác nhau cơ bản giữa form_with với form_tag và form_for ...

Trong các phiên bản từ Rails 5.1 trở về trước, form_tag và form_for chắc hẳn đã rất quen thuộc với nhiều người. Nhưng chúng không còn được sử dụng nhiều và sẽ dần bị thay thế bởi form_with (Rails 5.1) trong tương lai.
Dưới đây, là một số sự khác nhau cơ bản giữa form_with với form_tag và form_for được minh họa qua các ví dụ cụ thể.

1. Một cú pháp cho tất cả

Khi muốn tạo form mà không có đối tượng, chúng ta sử dụng form_tag

<%= form_tag users_path do %>
  <%= text_field_tag :email %>
  <%= submit_tag %>
<% end %>

Còn khi có một đối tượng, dùng form_for. Nó thường được sử dụng khi tạo mới hay cập nhất một đối tượng.

<%= form_for @user do |f| %>
  <%= f.text_field :email %>
  <%= f.submit %>
<% end %>

Ta thấy rằng, cú pháp của hai form trên có sự khác nhau. Bởi do form_for sử dụng form builder field helper để tạo form, còn form_tag thì không.
Nhưng với form_with thì không như vậy, chúng ta sử dụng form builder cho tất cả các field mọi lúc. Nó tạo form khi có đối tượng hay không có đều được, điều này giúp thuận tiện hơn và tránh sai cú pháp.
Khi không có đối tương, form_with

<%= form_with url: users_path do |f| %>
  <%= f.text_field :email %>
  <%= f.submit %>
<% end %>

Và có một đối tượng, form_with

<%= form_with model: @user do |f| %>
  <%= f.text_field :email %>
  <%= f.submit %>
<% end %>

Khi thêm các đối số cho đối tượng, các scope và url sẽ điều hướng từ đó, lúc này nó hoạt động tương tự form_for.

2. Không tự động thêm id và class

form_tag và form_for tự động khởi tạo id và class cho các trường của form. form_for còn thêm cả cho thẻ form.

<%= form_for User.new do |f| %>
  <%= f.text_field :email %>
<% end %>

sẽ tạo ra

<form class="new_user" id="new_user" action="/users" ...>
  ...
  <input type="text" name="user[email]" id="user_email" />
</form>

Với form_with thì phải tự thêm id và class bằng tay

<%= form_with model: @user do |f| %>
  <%= f.text_field :name %>
  <%= f.text_field :email, id: :email, class: :email %>
<% end %>

tạo ra

<form action="/users" ...>
  ...
  <input type="text" name="user[name]" />
  <input id="email" class="email" type="text" name="user[email]" />
</form>

Nếu muốn các label hoạt động, phải thêm id cho các trường của form.

<%= form_with model: @user do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name, id: :user_name %>
<% end %>

Chú ý: Từ Rails 5.2 form_with cũng sẽ tự động tạo id, do đó không cần phải chỉ định chúng theo cách thủ công nữa.

3. Các thuộc tính id và class của form_with không cần đóng gói nữa.

Trước đây thường viết

<%= form_for @user, html: { id: :custom_id, class: :custom_class } do |f| %>
  ...
<% end %>

Còn giờ chỉ đơn giản

<%= form_with model: @user, id: :custom_id, class: :custom_class do |f| %>
  ...
<% end %>

4. Các form fields không cần phải tương ứng với các thuộc tính của đối tượng

Lúc trước

<%= form_for @user do |f| %>
  <%= f.text_field :email %>
  <%= check_box_tag :send_welcome_email %>
<% end %>

Bây giờ

<%= form_with model: @user, local: true do |f| %>
  <%= f.text_field :email %>
  <%= f.check_box :send_welcome_email %>
  <%= f.submit %>
<% end %>

Lưu ý: send_welcome_email sẽ được gửi tới controller dưới dạng params[:user][:send_welcome_email]. Nên vẫn có thể sử dụng cả 2 cách check_box_tag hoặc f.check_box.

5. Tất cả các form đều mặc định ở chế độ remote

Đây là sự thay đổi thú vị. Mọi form được tạo bởi form_with sẽ được submit mặc định bởi request XHR (AJAX), không cần thêm tùy chọn remote: true như ở form_tag hay form_for. Chỉ cần làm thêm một chút công việc là tạo một JavaScript response template để nó hoạt động.
Tuy nhiên, nếu không muốn sử dụng remote: true cho form thì có thể sử dụng local: true

<%= form_with model: @user, local: true %>
  ...
<% end %>

6. Tổng kết

Bên trên chỉ là một vài điểm khác biệt của form_with, form_tag và form_for. Nhưng nó vẫn cho thấy những thuận lợi nhất định khi sử dụng form_with so với các phương pháp cũ.
Tóm tắt

form_tag form_for form_with
- Tạo form không có đối tượng. - Tạo form có đối tượng.
- Thường dùng khi tạo mới hay update một đối tượng.
- Tạo form có đối tượng hay không đều được.
- Thuận tiện, tránh sai cú pháp.
- Không sử dụng form builder field helper. - Sử dụng form builder field helper. - Sử dụng form builder cho tất cả các field.
- Tự động thêm id, class cho các form field. - Tự động thêm id, class cho cả thẻ form và các form field. - Không tự động thêm id, class cho thẻ form và form field.
--> Tự thêm bằng tay.
- Từ Rails 5.2 có tự động thêm id cho form.
- Các thuộc tính id, class cần đóng gói. - Các thuộc tính id, class cần được đóng gói. - Id và class không cần đóng gói nữa.
- Các form field không cần phải tương ứng với các thuộc tính của model.
- Không mặc định chế độ remote. - Không mặc định chế độ remote. - Mặc định chế độ remote.

Bài viết trên có tham khảo bài viết.

Bài liên quan

Phân biệt form_for, form_tag và form_with trong Rails

Trong các phiên bản từ Rails 5.1 trở về trước, form_tag và form_for chắc hẳn đã rất quen thuộc với nhiều người. Nhưng chúng không còn được sử dụng nhiều và sẽ dần bị thay thế bởi form_with (Rails 5.1) trong tương lai. Dưới đây, là một số sự khác nhau cơ bản giữa form_with với form_tag và form_for ...

Trịnh Tiến Mạnh viết 21:14 ngày 14/09/2018

Phân Biệt Node, Pod và Container trong Kubernetes

Kubernetes là công cụ dùng để quản lý việc triển khai (deploy), bảo trì (maintain) và mở rộng (scale) các ứng dụng được chạy bằng Docker container. Kubernetes là phần mềm mã nguồn mở và với các tính năng mạnh mẽ cung cấp Kubernetes đã nhanh chóng trở thành một công cụ không thể thiếu trong DevOps. ...

Vũ Văn Thanh viết 13:41 ngày 07/09/2018

Phân biệt lớp abstract và Interface trong Java

Cả lớp abstract và Interface được sử dụng để thu được tính trừu tượng, từ đó chúng ta có thể khai báo các phương thức trừu tượng. Cả lớp trừu tượng và Interface không thể được khởi tạo. Nhưng cũng có các điểm khác nhau giữa lớp trừu tượng và Interface, như sau: STT Lớp trừu tượng ...

Hoàng Hải Đăng viết 13:31 ngày 14/08/2018

Phân biệt class method và instance method trong ruby

Chắc hẳn một ruby newbie nào cũng đã từng gặp phải cú pháp self.method_name, khi đó chắc các bạn sẽ có một thắc mắc không biết là method này là dạng gì nhỉ. Sau đây mình xin chia sẻ với các bạn về hai method mà chúng ta dùng rất nhiều trong ngôn ruby đó là class method và instance method. Class ...

Tạ Quốc Bảo viết 18:00 ngày 12/08/2018

Sự khác biệt giữa render và redirect_to trong Rails

Với những người mới bắt đầu tìm hiểu về Ruby on Rails, phương thức render và redirect_to có thể dễ gây nhầm lẫn. Hai phương thức này đều xuất hiện ở cuối các action của controller, tạo HTTP response để trả về và sau cùng đều hiển thị view mới trên web browser. Bài viết sau đây sẽ chỉ ra sự khác ...

Bùi Văn Nam viết 17:19 ngày 12/08/2018
0