Giới thiệu về DataMapper
Giới thiệu chung Data Mapper là một mô hình ánh xạ hướng đối tượng (ORM). Khác với mô hình Active Record, Data Mapper giữ cho dữ liệu được lưu trong bộ nhớ máy và trong cơ sở dữ liệu độc lập với nhau. Mô hình Data Mapper phát huy hiệu quả trong các ứng dụng có số luật lệ và quy trình nghiệp vụ ...
Giới thiệu chung
Data Mapper là một mô hình ánh xạ hướng đối tượng (ORM). Khác với mô hình Active Record, Data Mapper giữ cho dữ liệu được lưu trong bộ nhớ máy và trong cơ sở dữ liệu độc lập với nhau. Mô hình Data Mapper phát huy hiệu quả trong các ứng dụng có số luật lệ và quy trình nghiệp vụ phức tạp, hoặc khi phát triển một ứng dụng mới từ cơ sở dữ liệu có sẵn.
Thư viện DataMapper là một trong những thư viện phổ biến để cài đặt và sử dụng mô hình Data Mapper cho Ruby. Bài mày sẽ giới thiệu những bước đơn giản nhất để làm quen với thư viện này.
Cài đặt
Bước đầu tiên là cài đặt các gem cần thiết bằng câu lệnh: gem install data_mapper Câu lệnh này cài đặt phần lớn các gem cận thiết:
- dm-core
- dm-aggregates
- dm-constraints
- dm-migrations
- dm-transactions
- dm-serializer
- dm-timestamps
- dm-validations
- dm-types
Sau đó, cài đặt một gem adapter tùy thuộc vào cơ sở dữ liệu đang sử dụng: dm-sqlite-adapter, dm-mysql-adapter hoặc dm-postgres-adapter
Để sử dụng thư viện DataMapper vào trong project, ta gọi: require "data_mapper"
Tạo model
Dưới đay là một lớp model đơn giản sử dụng DataMapper
class User include DataMapper::Resource property :id, Serial property :username, String property :email, String end
Module DataMapper::Resource được include vào trong lớp cung cấp các hàm cơ bản của thư viện. Như ví dụ ở trên, hàm property được sử dụng để tạo ba thuộc tính cho lớp: id, username và email. Trong đó, Serial là thuộc tính để tạo số tự nhiên tăng dần đóng vai trò khóa chính của lớp.
Migrate cơ sở dữ liệu
Sau khi tạo xong các model, công việc tiếp theo là migrate cơ sở dữ liệu. DataMapper cung cấp hai hàm thực hiện việc này:
DataMapper.auto_migrate! DataMapper.auto_upgrade!
Điểm khác biệt là hàm auto_migrate! sẽ xóa sạch toạn bộ dữ liệu trong cơ sở dữ liệu và tạo một schema mới; trong khi đó hàm auto_upgrade! cố gắng tìm ra những yêu cầu thay đổi với cơ sở dữ liệu và thực hiện thay đổi vào schema. Cả hai hàm này đều có thể gọi sau khi đọc một lớp bất kì. Dĩ nhiên, không ai muốn chạy auto_migrate! sau mỗi lần đọc một lớp, mà sẽ chạy auto_upgrade! sau mỗi lần reload trong quá trình development. Vấn đề này được giải quyết như sau:
configure :development do DataMapper.auto_upgrade! end
Ta có thể thấy rằng, cho đến lúc này, ta vẫn chưa phải sử dụng bất cứ câu truy vấn SQL nào; đó chính là đặc trưng của các mô hình ORM khi ta chỉ cần viết code bình thường mà vẫn có thể làm việc với các cơ sở dữ liệu quan hệ.
Thêm các thuộc tính
Sau các bước khởi tạo model và cơ sở dữ liệu, bây giờ ta sẽ cải tiến cho các model này, bắt đầu từ việc thêm các nhãn thời gian.
Nhãn thời gian
Trong các gem của DataMapper, gem dm-timestamps sẽ đảm nhận công việc này. Tất cả những gì cần làm là thêm vào các thuộc tính created_at và updated_at vào model, gem này sẽ tự động xử lý với các trường này khi cần.
property :created_at, DateTime property :updated_at, DateTime
Dĩ nhiên, ta có thể không thêm hai thuộc tính này, nếu thực sự thấy không cần thiết.
Các tùy chọn
Có một số tùy chọn có thể thêm vào các thuộc tính. Ví dụ, ta có thể xác định xem thuộc tính đó có cần phải có hay không, có là duy nhất hay không, hoặc xác định giá trị mặc định cho trường đó. Dưới đây là một ví dụ:
class Post include DataMapper::Resource property :slug, String, key: true, unique_index: true, default: ->{|resource,prop| resource.title.downcase.gsub " ", "-"} property :title, String, required: true property :body, Text, required: true property :created_at, DateTime property :updated_at, DateTime end
Ở ví dụ trên, các trường title và body là các trường buộc phải có. Ta xác định thuộc tính slug là khóa chính, bắt buộc trường này phải là duy nhất và được đánh index. Vì thế, giá trị mặc định của slug không phải là một giá trị cố định. Thay vào đó, giá trị mặc định của slug sẽ lấy từ resource truyền vào của DataMapper, hay từ bảng Post trong cơ sở dữ liệu, lấy thuộc tính title của nó, cho đi qua các hàm downcase (chuyển chữ hoa thành chữ thường) và gsub (chuyển các dấu trắng thành gạch dưới '_'). Nhờ đó, từ một xâu: "This is a Title"
Sẽ trở thành: "this-is-a-title"
Validations
Ta có thể thêm validation vào trong các tùy chọn của thuộc tính. Ví dụ:
property :email, String, format: :email_address property :password, String, length: 10..255
Associations
Thiết lập các quan hệ, khóa ngoài của thư viện DataMapper cũng tương tự như thư viện ActiveRecord. Ví dụ ta muốn tạo model User có nhiều Post, và model Post thuộc về User.
Ở model User, thêm dòng này:
has n, :posts
Sau đó, ở model Ost, thêm dòng này:
belongs_to :user
Cơ sở dữ liệu sẽ tự thêm vào thuộc tính user_id cho bảng Post.
Các từ khóa Associations dùng trong DataMapper và các từ khóa tương ứng trong ActiveRecord:
**DataMapper** **ActiveRecord** has n has_many has 1 has_one belongs_to belongs_to has n, :things, :through => Resource has_and_belongs_to_many has n, :things, :through => :model has_many :association, :through => Model
Accessors
Nếu muốn thay đổi đầu vào của các thuộc tính, ta có thể tự định nghĩa các hàm accessor. Ví dụ, trong model User trường name luôn được lưu trữ dưới dạng chữ thường. Ta có thể viết một hàm accessor như với một lớp bình thường. Bằng phương pháp này, ta có thể lấy giá trị nhập vào của đối tượng và lưu trữ theo cách ta mong muốn.
def name= new_username super new_username.downcase end
Ở đây, ta định nghĩa hàm name=, nhờ thế mà mỗi khi nhập một name mới, nó sẽ được lưu trữ bằng chữ thường.
Một số thư viện khác
Bên cạnh DataMapper, còn có những thư viện khác hỗ trợ cài đặt mô hình Data Mapper cho Ruby:
- Perpetuity
- Ruby Object Mapper (ROM)