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.