12/08/2018, 18:15

Tìm hiểu về Nested Attributes trong Ruby on rails

Xin chào các bạn đây là bài viết đầu tiên của tôi trên viblo, tôi là một new dev về Ruby, vì vậy việc tìm hiểu về các công nghệ, kỹ thuật mới là việc không thể thiếu. Chính vì vậy, hôm nay chúng ta sẽ cùng tìm hiểu về kỹ thuật Nested Atrributes nhé. Mở đầu về Nested Attributes Kỹ thuật này cho ...

Xin chào các bạn đây là bài viết đầu tiên của tôi trên viblo, tôi là một new dev về Ruby, vì vậy việc tìm hiểu về các công nghệ, kỹ thuật mới là việc không thể thiếu. Chính vì vậy, hôm nay chúng ta sẽ cùng tìm hiểu về kỹ thuật Nested Atrributes nhé.

Mở đầu về Nested Attributes

Kỹ thuật này cho phép chúng ta có thể dễ dàng khởi tạo và lưu thuộc tính của đối tượng thông qua đối tượng cha của nó (associated records). Mặc định thì rails app của bạn sẽ không kích hoạt Nested attribute, nhưng để kích hoạt nó cũng khá đơn giản và chúng ta cùng xem qua một ví dụ dưới đây để có cái nhìn tổng quát về Nested attribute nhé.

Ví dụ nhỏ

Tôi muốn xây dựng một web, trong đó có 2 model là User và Log, User dùng để lưu thông tin người dùng, Log dùng để ghi lại nhật ký. Tóm lại ý tưởng của tôi là khi tạo mới 1 user thì ta sẽ tạo 1 bản ghi và lưu vào Log. Vậy là ví dụ này ta có thể dùng nested attributes rồi nhé.

Thực hiện ví dụ

Đầu tiên ta tạo mới 1 project:

rails new demo

Khởi tạo 2 model là User và Log:

rails g model User name:string
rails g model Log log_content:string user:references
rake db:migrate

Tiến hành tạo user_controller.rb

rails g controller Users new create

Vậy là các bước khởi tạo project đã xong, giờ chúng ta cùng xây dựng 1 ứng dụng với kỹ thuật Nested attributes nhé. Vì chúng ta muốn đồng thời tạo mới bản ghi là Log khi ta tạo mới 1 User nên trong model user ta cần bật nested attributes bằng cách accepts_nested_attributes_for :model tương ứng. Và cụ thể là: app/models/user.rb

class User < ApplicationRecord
  has_many :logs
  accepts_nested_attributes_for :logs
end

Viết hàm create, new trong app/controllers/users_controller.rb

class UsersController < ApplicationController
  def new
    @user = User.new
    @user.logs.build
  end

  def create
    @user= User.new user_params
    if @user.save
      flash[:success] = "Create new User successfully"
    else
      flash[:success] = "Create new User fail"
    end
    redirect_to root_url
  end

  private

  def user_params
    params.require(:user).permit :name, logs_attributes: [:id, :log_content]
  end
end

Ở strong params bạn chú ý ta đã khai báo phương thức logs_attributes. Viết thêm view cho app/views/users/new.html.erb

<%= form_for @user do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
  <%= f.fields_for :logs do |logs_form| %>
    <%= logs_form.label :log_content %>
    <%= logs_form.text_field :log_content %>
  <% end %>
  <%= f.submit "Create" %>
<% end %>

Fields_for tạo ra một scope xung quanh một đối tượng cụ thể như form_for, nhưng không tạo các thẻ form. Điều này làm cho fields_for phù hợp để xác định các đối tượng mô hình bổ sung trong cùng một form của chính nó. Nói một cách đơn giản thì bạn dùng fields_for để xác định đối tượng mà bạn muốn khởi tạo hoặc cập nhật trong nested atttribute.

Kết quả!

Và kết quả khi ta tạo mới 1 user thì ta sẽ tạo được 1 log theo user vừa khởi tạo đó.

Ngoài ra bạn có thể tham khảo thêm các tuỳ biến khác của accepes_nested_attributes_for đó là :allow_destroy, :reject_if, :limit, :update_only. Các bạn có thể tham khảo tại Tại đây

Tổng kết

Trên đây là những gì mà mình mới tìm hiểu được về Nested attributes. Bài viết sẽ có những thiếu sót nhất định, vì vậy rất mong có sự góp ý của các bạn để làm bài viết được hoàn thiện hơn. Mình xin cảm hơn! Link bài viết tham khảo http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

0