+4

Tìm hiểu về nested attributes trong rails

1.Nested Attributes là gì?

Nested attributes là kỹ thuật mới được tích hợp vào phiên bản rails 4.0, nó cho phép bạn lưu thuộc tính của 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 tắt 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 LessonsController < ApplicationController
  def create
    @lesson = Lesson.new lesson_params
  end

  private
  def lesson_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
  • :reject_if
  • :limit
  • :update_only

Các bạn có thể tham khảo thêm tại http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

Bài viết đầu tiên còn nhiều thiếu sót rất mong các bạn thông cảm. Xin cảm ơn các bạn đã theo dõi!


All Rights Reserved

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