Model, Database trong Lotus Framwork
Bài đăng này đã không được cập nhật trong 3 năm
1 Model
- Lotus có xây dựng một ORM riêng, gọi là lotus-model và xây dựng dựa trên sequel. Lotus model cung cấp cho bạn các thành phần chính sau:
- Entity – An object defined by its identity.
- Repository – An object that mediates between the entities and the persistence layer.
- Data Mapper – A persistence mapper that keep entities independent from database details.
- Adapter – A database adapter.
- Query – An object that represents a database query.
1.1 Entity là gì?
- Entity là 1 object nó được định nghĩa dựa vào những gì nó có.
- Ví dụ: ta có 1 Article và ta cần biết thông tin gì về user như title, content, user_id...
- Theo như mô tả ở trên thì Entity là Article, và Article được định nghĩa dựa trên title, content, user_id...
- Cách định nghĩa 1 Entity
require 'lotus/entity'
class Article
include Lotus::Entity
attributes :title, :content, :user_id, :created_at, :updated_at
end
1.2 Repository là gì?
- Repository nó giống như là một trung gian giúp bạn giao tiếp với cơ sở dữ liệu một cách dễ dàng hơn hay nói cách khác thì repository sẽ làm nhiệm vụ persist data cũng như query logic
- Ví dụ: theo như mô tả 1 Article trên nếu chúng ta muốn lưu 1 article thì phải làm như thế nào?--> Repository sẽ giúp chúng ta làm những công việc đó
require 'lotus/repository'
class ArticleRepository
include Lotus::Repository
end
- Về query logic
# thông tin về 1 article
article = Article.new(title: 'bai 1', content: 'hello world')
# tạo 1 new article trong repository
ArticleRepository.create(article)
# giờ ta thay đổi title của article
article.title = 'lesson1'
article = ArticleRepository.update(article)
# remove article khỏi list
ArticleRepository.delete(article)
- Việc query data trong lotus không giống như ActiveRecord nữa. Trong repository thì query là một private component. Nghĩa là các query logic của bạn sẽ được encapsulated, khi dùng thì chỉ cần gọi ra method cần thiết của Repository class thôi, còn logic như nào thì không visible nữa.
1.3 Data Mapper là gì?
- Để lotus-model biết được là phải map column nào dưới database lên attribute nào của entity, ta cần phải map chúng lại với nhau. Trong folder config, mình có sẵn một file mapping.rb, là nơi bạn sẽ khai báo tất cả các mapping giữa entity với table.
collection :articles do
entity Article
repository ArticleRepository
attribute :id, Integer
attribute :title, String
attribute :content, String
attribute :user_id, Integer
attribute :created_at, DateTime
attribute :updated_at, DateTime
end
Trong đó
- collection :articles => table articles trong database
- entity Article => mỗi record trong table articles ứng với một instance article của class Article
- repository ArticleRepository => khai báo repository cho Artilce, giúp tách rời nhiệm vụ persist data, query logic ra khỏi model
- attribute: map column và attribute giữa database với Ruby object.
Tuy nhiên ta cần phải config thêm trong file lotus-part1.rb để báo cho Lotus biết là bạn định nghĩa mapping trong file mapping.rb
mapping "#{__dir__}/config/mapping"
Ngoài viết mapping trong file mapping.rb thì chúng ta có thể viết inline trực tiếp trong file config lotus-part1.rb
như sau
mapping do
collection :articles do
entity Article
repository ArticleRepository
attribute :id, Integer
attribute :title, String
attribute :content, String
attribute :user_id, Integer
attribute :created_at, DateTime
attribute :updated_at, DateTime
end
end
###1.4 Query
- Về cách query dữ liệu trong lotus cơ bản như Active Record chỉ khác là cách thể hiện và chỗ viết các câu query, trong lotus thì viết ở repository
- Ví dụ :
- In Active Record:
Article.where(user_id: user.id).order(:created_at).limit(10)
- In lotus:
class ArticleRepository
include Lotus::Repository
def self.most_recent_by_user(user, limit: 10)
query do
where(user_id: user.id).order(:created_at)
end.limit(limit)
end
end
##2 Database
- Ta có thể lựa chọn adapter trong file lotus-tutorial.rb, bạn sẽ thấy phần comment giới thiệu cũng như hướng dẫn cấu hình
# * SQL adapter
adapter type: :sql, uri: 'sqlite://db/lotus-part1_development.sqlite3'
# adapter type: :sql, uri: 'postgres://localhost/lotus-part1_development'
# adapter type: :sql, uri: 'mysql://localhost/lotus-part1_development'uby
Ở đây tôi dùng sqlite
- Lotus hỗ trợ 3 loại adapters
- File system (default)
- Memory
- SQL
Tùy vào môi trường thì sẽ dùng các config khác nhau
- Ví dụ môi trường dev thì config như sau
# Define ENV variables for development environment
LOTUS_PART1_DATABASE_URL="sqlite:///db/lotus-part1_development" //đường dẫn tới file db trong project
WEB_SESSIONS_SECRET="7c0fd875aa778bf97ebcff1eb5eef60a1d2c2fb690c48297947ffb4658ce5277"
- Để test xem url của bạn có đúng không thì chỉ cần chạy lệnh
lotus db create
###2.1 Generate migration
lotus generate migration create_articles
- Lotus migration cũng tương tự như Rails migration. Lúc này lotus sẽ tạo dùm bạn một file mới trong folder db/migrations, prefix sẽ là timestamp lúc generate ra.
Lotus::Model.migration do
change do
create_table :articles do
primary_key :id
column :user_id, Integer
column :title, String, null: false
column :content, String
column :created_at, DateTime
column :updated_at, DateTime
end
end
end
sau đó chạy lệnh bundle exec lotus db migrate
để run file migrate
###2.2 Tạo seeds data
- Về tạo data mẫu trong lotus thì không có gì khác so với rails
[
{
title: "Article1",
content: "Nguyen Van Dung",
user_id: 1
},
{
title: "Article2",
content: "Pham Thi Chieu",
user_id: 1
}
].each do |article|
new_article = Article.new(article)
ArticleRepository.persist(new_article)
end
- Viết rake file để chạy file seeds
namespace :db do
task :migrate do
require_relative 'lib/lotus-part1/migrator'
LotusPart1::Migrator.migrate!
end
task :seed => [:migrate] do
load 'db/seeds.rb'
end
end
Chạy lệnh bundle exec rake db:seed
để run file seeds.rb
Source code tại đây
All rights reserved