article model 和 article migration
schema "articles" do
field :title, :string
field :body, :string
field :reading, :integer, default: 0
belongs_to :category, HelloPhoenix.Category, foreign_key: :category_id
has_many :comments, HelloPhoenix.Comment, on_delete: :delete_all
many_to_many :tags, HelloPhoenix.Tag, join_through: "articles_tags", on_delete: :delete_all
timestamps()
end
def change do
create table(:articles) do
add :title, :string
add :body, :string
add :category_id, references(:categorys, on_delete: :nothing)
timestamps()
end
create index(:articles, [:category_id])
end
tag model 和 tag migrartion
schema "tags" do
field :name, :string
many_to_many :articles, HelloPhoenix.Article, join_through: "articles_tags", on_delete: :delete_all
timestamps()
end
def change do
create table(:tags) do
add :name, :string
timestamps()
end
create unique_index(:tags, [:name])
end
article_tag model 和article_tag migration,添加article_tag model主要是为了方便之后对articles_tags进行数据库操作,因为phoenix的多对多api功能不全
schema "articles_tags" do
field :article_id, :integer
field :tag_id, :integer
end
def change do
create table(:articles_tags, primary_key: false) do
add :article_id, references(:articles)
add :tag_id, references(:tags)
end
end
如上在tag和article model中加入on_delete: delete_all就可以在删除tag或者article的时候自动删除article_tag数据表中的数据。
关于article controller我是这么写的, 创建文章勾选tag的时候, tag_ids为勾选的tags id
article
|> Repo.preload(:tags)
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(:tags, Enum.map(tag_ids, fn id -> Repo.get(Tag, id) end))
|> Repo.update!
编辑文章的时候,先删除在articles_tags表中关于这篇文章的所有关联,然后重新插入新的关联关系
from(p in ArticleTag, where: p.article_id == ^id) |> Repo.delete_all # 删除之前所有关联
article # 重新插入所有关联
|> Repo.preload(:tags)
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(:tags, Enum.map(tag_ids, fn id -> Repo.get(Tag, id) end))
|> Repo.update!
评论
试着评价一下