Loading...
Loading...
Compare original and translation side by side
schema "cart_items" do
field :product_id, :integer # Reference by ID
# NOT: belongs_to :product, Catalog.Product
endschema "cart_items" do
field :product_id, :integer # 用ID引用
# 不要写:belongs_to :product, Catalog.Product
enddef create_product(params) do
params
|> Products.build() # Factory: unstructured → domain
|> Products.validate() # Aggregate: enforce invariants
|> Products.insert() # Repository: persist
enddef create_product(params) do
params
|> Products.build() # 工厂:非结构化数据 → 领域对象
|> Products.validate() # 聚合:强制约束不变量
|> Products.insert() # 仓库:持久化
end| Use Case | Approach |
|---|---|
| Database table | Standard |
| Form validation only | |
| API request/response | Embedded schema or schemaless |
| 用例 | 实现方式 |
|---|---|
| 数据库表 | 标准 |
| 仅表单验证 | |
| API 请求/响应 | 嵌入式Schema或无Schema |
def registration_changeset(user, attrs) # Full validation + password
def profile_changeset(user, attrs) # Name, bio only
def admin_changeset(user, attrs) # Role, verified_atdef registration_changeset(user, attrs) # 完整验证 + 密码处理
def profile_changeset(user, attrs) # 仅处理名称、简介
def admin_changeset(user, attrs) # 处理角色、验证时间add :post_id, references(:posts, with: [org_id: :org_id], match: :full)prepare_query/3org_idadd :post_id, references(:posts, with: [org_id: :org_id], match: :full)prepare_query/3org_id| Approach | Best For |
|---|---|
| Separate preloads | Has-many with many records (less memory) |
| Join preloads | Belongs-to, has-one (single query) |
| 方式 | 适用场景 |
|---|---|
| 单独预加载 | 包含大量记录的has-many关联(内存占用更少) |
| 关联查询预加载 | belongs-to、has-one关联(单查询) |
"If you have a CRUD bounded context, go for it. No need to add complexity."
“如果你的限界上下文是CRUD类型,直接用就好。无需额外增加复杂度。”
%{recursive_query | prefix: "tenant"}%{recursive_query | prefix: "tenant"}WHERE id = $1prepare: :unnamedWHERE id = $1prepare: :unnamedpool_countpool_sizepool_countpool_sizeString.replace(string, "\x00", "")String.replace(string, "\x00", "")has_many :comments, Comment, preload_order: [desc: :inserted_at]throughhas_many :comments, Comment, preload_order: [desc: :inserted_at]throughEcto.Migrator.run(Repo, [{0, Migration1}, {1, Migration2}], :up, opts)Ecto.Migrator.run(Repo, [{0, Migration1}, {1, Migration2}], :up, opts)Repo.insert/1Repo.insert!/1{:ok, _}{:error, _}Repo.transact/1Ecto.MultiRepo.insert/1Repo.insert!/1{:ok, _}{:error, _}Repo.transact/1Ecto.Multiprepare: :unnamedprepare: :unnamed