gpt4 book ai didi

elixir - 管理多对多关联

转载 作者:行者123 更新时间:2023-12-04 00:49:44 24 4
gpt4 key购买 nike

说,我有属于许多标签的 Post 模型:

defmodule MyApp.Post do
use MyApp.Web, :model

schema "tours" do
field :title, :string
field :description, :string
has_many :tags, {"tags_posts", MyApp.Tag}
end

# …
end

保存帖子时,我从多选字段中获取 tags_ids 列表,如下所示:
tags_ids[]=1&tags_ids[]=2

问题是如何在 Phoenix 保存时将标签链接到帖子?

最佳答案

ecto 尚不支持嵌套变更集:https://github.com/elixir-lang/ecto/issues/618您必须自己保存标签。

在下面的代码片段中,我将选择 tag_ids如果 Post.changeset/2,则将它们插入连接表中给我一个有效的结果。为了在表单中保留选定的标签,我添加了一个虚拟字段,我们可以在表单中读取并设置默认值。这不是最好的解决方案,但对我有用。

PostController

def create(conn, %{"post" => post_params}) do
post_changeset = Post.changeset(%Post{}, post_params)

if post_changeset.valid? do
post = Repo.insert!(post_changeset)

case Dict.fetch(post_params, "tag_ids") do
{:ok, tag_ids} ->

for tag_id <- tag_ids do
post_tag_changeset = PostTag.changeset(%PostTag{}, %{"tag_id" => tag_id, "post_id" => post.id})
Repo.insert(post_tag_changeset)
end
:error ->
# No tags selected
end

conn
|> put_flash(:info, "Success!")
|> redirect(to: post_path(conn, :new))
else
render(conn, "new.html", changeset: post_changeset)
end
end

后置模型
schema "posts" do
has_many :post_tags, Stackoverflow.PostTag
field :title, :string
field :tag_ids, {:array, :integer}, virtual: true

timestamps
end

@required_fields ["title"]
@optional_fields ["tag_ids"]

def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end

PostTag型号 (JoinTable 用于创建多对多关联)
schema "post_tags" do
belongs_to :post, Stackoverflow.Post
belongs_to :tag, Stackoverflow.Tag

timestamps
end

@required_fields ["post_id", "tag_id"]
@optional_fields []

def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end

邮政表格
<%= form_for @changeset, @action, fn f -> %>

<%= if f.errors != [] do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below:</p>
<ul>
<%= for {attr, message} <- f.errors do %>
<li><%= humanize(attr) %> <%= message %></li>
<% end %>
</ul>
</div>
<% end %>

<div class="form-group">
<%= label f, :title, "Title" %>
<%= text_input f, :title, class: "form-control" %>
</div>

<div class="form-group">
<%= label f, :tag_ids, "Tags" %>
<!-- Tags in this case are static, load available tags from controller in your case -->
<%= multiple_select f, :tag_ids, ["Tag 1": 1, "Tag 2": 2], value: (if @changeset.params, do: @changeset.params["tag_ids"], else: @changeset.model.tag_ids) %>
</div>

<div class="form-group">
<%= submit "Save", class: "btn btn-primary" %>
</div>

<% end %>

如果要更新标签,您有两个选择。
  • 全部删除并插入新条目
  • 查找更改,并保留现有条目

  • 我希望它有帮助。

    关于elixir - 管理多对多关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31641066/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com