create multiple object with Nested attributes
Nested attrbutes là một kỹ thuật xử lý params mới được tích hợp từ phiên bản 4.0 của framework Ruby on Rails cung cấp một công cụ khá mạnh mẽ và thuận lợi cho developer làm việc với form. Nếu chưa có sự xuất hiện của Nested attributes developer khi thực hiện các thao tác liên quan tới đăng ký, ...
Nested attrbutes là một kỹ thuật xử lý params mới được tích hợp từ phiên bản 4.0 của framework Ruby on Rails cung cấp một công cụ khá mạnh mẽ và thuận lợi cho developer làm việc với form.
Nếu chưa có sự xuất hiện của Nested attributes developer khi thực hiện các thao tác liên quan tới đăng ký, update luôn phải xử lý params với những câu lệnh đơn thuần mặc dù nhận được sự tùy biến nhưng đối với những form lớn hoặc mối quan hệ phức tạp thì thật sự không phải là giải pháp quá tốt. Controller nặng nề không giữ được sự nhẹ nhàng cần có sẽ khiến cho hệ thống ì ạch và khó khăn trong việc bảo trì.
Nested sẽ gói gọn tất cả những thao tác phức tạp đó trong bằng một vài cú pháp đơn giản, sáng sủa công việc của developer chỉ là khai báo, sử dụng thêm chút sáng tạo sẽ mang lại hiệu quả cao.
Chuẩn bị##
Bắt đầu với new project.###
rails new demo-nested
Create model:###
rails g model hotel rails g model room_categories
app/model/hotel.rb##
class Hotel < ActiveRecord::Base has_many :room_categories, dependent: :destroy validates :name, presence: true end
app/model/room_category.rb##
class RoomCategory < ActiveRecord::Base belongs_to :hotel validates :name, presence: true end
1. Create object không có liên kết.##
app/controller/hotel_controller.rb##
def new @hotel = Hotel.new end def create hotel = Hotel.create hotel_params end private def hotel_params params.require(:hotel).permit :name end
app/views/hotel/new.html.erb
<% form_for @hotel do |f| %> <div class="field"> <%= f.label :name %><br> <%= f.text_field :name %> <%= f.submit %> </div> <% end %>
2. Create object có liên kết với field_for.##
Giả dụ sau khi muốn tạo hotel cần tạo luôn 2 room categories cho hotel đó khai báo thêm như sau:
app/controller/hotel_controller.rb##
def new @hotel = Hotel.new @hotel.room_categories.build end def create hotel = Hotel.create hotel_params end private def hotel_params params.require(:hotel).permit(:name, room_categories_attributes: [ :id, :name ]) end
app/views/hotel/new.html.erb
<% form_for @hotel do |f| %> <div class="field"> <%= f.label :name %><br> <%= f.text_field :name %> </div> <h2>Room Categories</h2> <%= f.fields_for :room_categories do |room_category| %> <div class="room_category_fields"> <div class="field"> <%= room_category.label :name %><br> <%= room_category.text_field :name %> </div> </div> <% end %> <%= f.submit %> <% end %>
app/model/hotel.rb##
class Hotel < ActiveRecord::Base has_many :room_categories, dependent: :destroy accepts_nested_attributes_for :room_categories end
Câu hỏi đặt ra là trong trường hợp muốn tạo multiple hotel thì có sử dụng nested được không? Câu trả lời là có tuy nhiên cần tùy biến một chút.
-
Sử dụng form_tag thay cho form_for
<%= form_tag hotels_path do |f| %> <div class="field"> <%= text_field_tag name: "hotels[][name]" %> <%= text_field_tag name: "hotels[][name]" %> </div> <% end %>
-
Tùy biến trong controller permit với một mảng hotel.##
private def hotel_params params.permit(hotels: name)[:hotels] end
Bài viết chỉ đề cập tới đăng ký với action update thì sử dụng nested tương tự. Controller ngắn gọn và rõ dàng dễ dàng lập trình và bảo trì. Rất mong nhận được đóng góp ý kiến từ các bạn.
Chúc các bạn thành công!!!