Ruby on Rails Nested Attributes
1.Nested Attributes là gì? Nested Attributes là một tính năng cho phép chúng ta lưu bản ghi này thông qua bản ghi khác (associated records). Mặc định trong rails thì nested atrributes updating được disable và bạn có thể kích hoạt nó bằng cách sử dụng phương thức accepts_nested_attributes_for ...
1.Nested Attributes là gì?
Nested Attributes là một tính năng cho phép chúng ta lưu bản ghi này thông qua bản ghi khác (associated records). Mặc định trong rails thì nested atrributes updating được disable và bạn có thể kích hoạt nó bằng cách sử dụng phương thức accepts_nested_attributes_for trong model tương ứng.
app/models/lesson.rb
class Lesson < ActiveRecord::Base has_many :results accepts_nested_attributes_for :results end
Ví dụ khi bạn sử dụng accepts_nested_attributes_for :results trong model Lesson thì khi create hoặc update cho đối tượng lesson bạn có thể create(update) luôn cho results bằng cách truyền thuộc tính của results vào lesson_params
app/controllers/lessons_controller.rb
class MembersController < ApplicationController def create @member = Member.new member_params end private def member_params params.require(:lesson).permit :name, results_attributes: [:id, :answer_id] end end
2. Sử dụng fields_for kết hợp với accepts_nested_attributes_for
Fields_for về cơ bản cũng gần giống form_for là tạo ra một scope xung quanh một đối tượng cụ thể nhưng không tạo ra form_tags chính nó. Vì thế fields_for thích hợp cho việc xác định các model object bổ sung trong cùng form đấy.
Đầu tiên các bạn vẫn khai báo method accept_nested_attributes_for trong model mình cần dùng:
app/models/lesson.rb
class Lesson < ActiveRecord::Base has_many :results accepts_nested_attributes_for :results end
app/models/result.rb
class Result < ActiveRecord::Base belong_to :lesson has_many :answer end
Tạo thêm thuộc tính cần update của đối tượng khác vào params của đối tượng cha. app/controllers/lessons_controller.rb
class MembersController < ApplicationController if @lesson.update_attributes lesson_params redirect_to lesson_path else flash[:danger] = "Update failed" redirect_to root_path end private def member_params params.require(:lesson).permit :name, results_attributes: [:id, :answer_id] end end
app/views/lesson/show.html.erb
<%= form_for @lesson do |f| %> <%= f.fields_for :results do |result| %> <% result.answers.each do |answer| %> <li> <label class="radio-inline"> <%= f.radio_button :answer_id, answer.id %> <%= answer.content %> </label> </li> <% end %> <% end %> <%= f.submit "Save", method: :update, data: {confirm: "Are you sure"} %> <% end %>
Tạo fields_for cho đối tượng results bên trong đối tượng lesson để thêm các thuộc tính cần thiết.Như vậy khi cập nhật lesson thì kết qủa của lesson tương ứng trong bảng result cũng được cập nhật.
3.Một số tùy biến khi sử dụng accepes_nested_attributes_for
- :allow_destroy True hoặc false, nếu là true thì có thể xóa record nào chưa key _destroy và giá trị là true
- :reject_if Cho phép bạn chỉ định một Proc hoặc một Symbol trỏ vào một phương thức để kiểm tra một bản ghi có được phép tạo ra hay không. reject_if được chỉ định khi giá trị của _destroy không phải là true. Sử dụng all_blank thay vì Proc sẽ tạo ra một proc từ reject những record mà tất cả các thuộc tính là blank và giá trịn trường _destroy không phải là true.
- :limit Cho phép bạn chỉ định số lượng tối đa của các record liên quan có thể được xử lý với các thuộc tính lồng nhau. :limit option chỉ áp dụng cho quan hệ one-to-many.
- :update_only Cho phép bạn chỉ định một record chỉ có thể được update thôi. Một record mới được tạo ra khi ko có record nào hiện có. :update_only chỉ hoạt động cho quan hệ one-to-one.
Cảm ơn các bạn đã đọc bài