12/08/2018, 15:41

Repository Pattern in Rails

Gần đây mình có tìm hiểu về Ruby on Rails, trước đó mình code PHP trên framework Laravel. Những ai làm Laravel thì chắc quen với Repository Pattern. Repository là một phong cách thiết kế code thực hiện việc tách biệt giữa data access logic và business logic, nó được thực hiện bằng cách thêm vào ...

Gần đây mình có tìm hiểu về Ruby on Rails, trước đó mình code PHP trên framework Laravel. Những ai làm Laravel thì chắc quen với Repository Pattern. Repository là một phong cách thiết kế code thực hiện việc tách biệt giữa data access logic và business logic, nó được thực hiện bằng cách thêm vào một tầng nằm giữa Business Logic và Data Source, gọi là các Repository - nơi lưu trữ tất cả code liên quan đến việc truy cập dữ liệu. Khi nhảy vào học Rails, mình cũng tìm hiểu ngay về vấn đề này. Bài viết hôm nay mình sẽ demo nho nhỏ về Repository trong Rails. Bây giờ chúng ta hãy cùng xem một action create quen thuộc dưới đây nhé

def create
    @user = User.new(user_params)
    if @user.save
      redirect_to user_path(@user), notice: 'User has been created'
    else
      render :new
    end
  end

Rất là quen thuộc phải không các bạn. Còn có thêm protecting attributes user_params nữa nhưng mình không cho vào, chắc các bạn cũng biết rồi. Mà mình thấy lúc trước có thể dùng attr_accessible mà không rõ lý do gì mà nó lại bị khai tử và bắt mình phải viết thêm method user_params nựa, hay họ sợ developer nhầm lẫn giữa attr_accessible và attr_accessor chăng, thôi kệ đi. Bây giờ chúng ta sẽ tiến hành tách ra bằng việc sử dụng Repository pattern để trừu tượng hóa cách tương tác với cơ sở dữ liệu. Các bạn hãy tạo lớp UserRepository trong thư mục app/repositories chịu trách nhiệm tương tác với cơ sở dữ liệu nhé.

class UserRepository
  def all
    User.all
  end

  def find(id)
    User.find(id)
  end

  def new_entity(attrs = nil)
    User.new(attrs)
  end

  def save(user)
    user.save
  end

  def delete(user)
    user.destroy
  end
end

Bây giờ thì bạn có thể sử dụng trong controller rồi

class UsersController < ApplicationController
  before_action :set_user, only: [:edit, :show]
 
  def show
  end
  
  def create
    @user = repo.new_entity(user_params)
    
    if repo.save(@user)
      redirect_to user_path(@user), notice: 'User has been created'
    else
      render :new
    end
  end
  
  def edit
  end
  
  private
  
  def set_user
    @user = repo.find(params[:id])
  end

  def user_params
    params.require(:user).permit(:first_name, :last_name, :password)
  end
  
  def repo
    @repo ||= UserRepository.new
  end
end

Việc sử dụng Repository đem lại một số lợi ích sau:

  • Chúng ta không phải tương tác trực tiếp mới model trong controller nữa.
  • Cấu trúc code dễ nhìn và dễ hiểu
  • Code dễ đọc hơn, chúng ta chỉ cần focus vào data access logic nên khi có thay đổi gì thì cũng sẽ dễ dàng hơn trong việc maintain code.

Để triễn khai đúng Repository Pattern thì bạn cần phải tạo ra BaseRepository và định nghĩa các method thường được sử dụng trong lớp này, ứng với mỗi model thì ta sẽ tạo ModelNameRepository kế thừa từ BaseRepository. ModelNameRepository chỉ cần định nghĩa thêm những phương thức của riêng nó, còn các phương thức cơ bản như find, all.. đã có trong Base rồi. Việc làm này nhằm tăng tính tái sử dụng và giảm thiểu trùng lặp code.

Trên đây là những chia sẽ của mình về cách sử dụng Repository trong Rails, hi vọng nó sẽ hữu ích cho các bạn.

0