Tôi có một mô hình Ecto như vậy:Xây dựng một bản đồ JSON cho một tự tham khảo Ecto mô hình
defmodule Project.Category do
use Project.Web, :model
schema "categories" do
field :name, :string
field :list_order, :integer
field :parent_id, :integer
belongs_to :menu, Project.Menu
has_many :subcategories, Project.Category, foreign_key: :parent_id
timestamps
end
@required_fields ~w(name list_order)
@optional_fields ~w(menu_id parent_id)
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
Như bạn có thể thấy mô hình loại có thể tham khảo bản thân thông qua các nguyên tử tiểu thể loại.
Dưới đây là quan điểm liên quan đến mô hình này:
defmodule Project.CategoryView do
use Project.Web, :view
def render("show.json", %{category: category}) do
json = %{
id: category.id,
name: category.name,
list_order: category.list_order
parent_id: category.parent_id
}
if is_list(category.subcategories) do
children = render_many(category.subcategories, Project.CategoryView, "show.json")
Map.put(json, :subcategories, children)
else
json
end
end
end
Tôi có một nếu điều kiện trên tiểu thể loại để tôi có thể chơi đẹp với Poison khi họ không cài đặt sẵn.
Cuối cùng, đây là 2 chức năng điều khiển của tôi mà gọi quan điểm này:
defmodule Project.CategoryController do
use Project.Web, :controller
alias Project.Category
def show(conn, %{"id" => id}) do
category = Repo.get!(Category, id)
render conn, "show.json", category: category
end
def showWithChildren(conn, %{"id" => id}) do
category = Repo.get!(Category, id)
|> Repo.preload [:subcategories, subcategories: :subcategories]
render conn, "show.json", category: category
end
end
Chức năng show
hoạt động tốt:
{
"parent_id": null,
"name": "a",
"list_order": 4,
"id": 7
}
Tuy nhiên, chức năng showWithChildren
tôi được giới hạn trong 2 mức độ làm tổ vì về cách tôi sử dụng tải trước:
{
"subcategories": [
{
"subcategories": [
{
"parent_id": 10,
"name": "d",
"list_order": 4,
"id": 11
}
],
"parent_id": 7,
"name": "c",
"list_order": 4,
"id": 10
},
{
"subcategories": [],
"parent_id": 7,
"name": "b",
"list_order": 9,
"id": 13
}
],
"parent_id": null,
"name": "a",
"list_order": 4,
"id": 7
}
Ví dụ: mục danh mục 11 ở trên cũng có các danh mục con nhưng tôi không thể tiếp cận chúng. Các danh mục phụ đó cũng có thể có chính các danh mục phụ, do đó độ sâu tiềm năng của hệ thống phân cấp là n.
Tôi biết rằng tôi cần một số phép thuật đệ quy nhưng vì tôi mới dùng cả lập trình hàm và Elixir, tôi không thể quấn đầu quanh nó. Bất kỳ trợ giúp nào cũng được đánh giá rất cao.
Hoạt động tuyệt vời. :) Điều đáng nói đến là repo của dự án nên được thêm vào như một bí danh, vì chế độ xem không có chúng theo mặc định. Tôi sẽ xem xét việc chăm sóc điều này ở phía DB chứ không phải là ứng dụng. Cảm ơn! – user1112789
@ jose-valim là ltree thay thế đẹp hơn cho vấn đề này? – user2290820