Elixir/Phoenix通过表单将a.相关实体添加到现有实体中



我对长生不老药/凤凰还很陌生,我对一个概念有点了解。我找到了一个变通办法,但我对此并不满意。

上下文:我创建了一个";项目";在我的数据库中。现在我想创建一个";工作项";通过项目与项目相关的;显示";页由于它与特定的项目有关,我需要将ID添加到变更集中。

我试着在projects_controller中这样做:

def show(conn, %{"id" => id}) do
project   = Clients.get_project!(id)
changeset = Clients.change_work_item(%BudgetItem{project_id: project.id})
render(conn, "show.html", project: project, changeset: changeset)
end

这是形式:

%= form_for @changeset, @action, fn f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<% end %>
<%= label f, :title %>
<%= text_input f, :title %>
<%= error_tag f, :title %>
<%= label f, "duration" %>
<%= number_input f, :amount_in_cents %>
<%= error_tag f, :amount_in_cents %>
<div>
<%= submit "Save" %>
</div>
<% end %>

当我点击提交时,project_id不在最终出现在work_item_controller中的变更集中——我的理解是,这是因为elixir中数据的不变性。我的解决方法是现在我在视图中有一个隐藏字段;商店";id(<%= hidden_input f, :project_id %>(。这是有效的,但我对此感到不满,因为用户可以干预它,而且感觉很好——;误用";这样做的视图。你们中有谁能向我解释一下通常是怎么做的吗?我一直找不到一个令人满意的解决方案。

如果您需要更多的代码来更好地理解实现,请告诉我。

谢谢你抽出时间!

编辑:

defmodule SthWeb.WorkItemController do
use SthWeb, :controller
alias Sth.Clients
alias Sth.Clients.Project
def create(conn, %{"work_item" => work_item_params}) do
case Clients.create_work_item(work_item_params) do
{:ok, work_item} ->
conn
|> put_flash(:info, "Budget increased successfully!")
|> redirect(to: Routes.project_path(conn, :show, work_item.project_id))
{:error, changeset} ->
conn
|> put_flash(:info, "Something went wrong.")
|> redirect(to: Routes.project_path(conn, :show, 1))
end
end
end

我认为您有很好的设置来处理您的情况。您的project_id来自用户所在的路径,在您的控制器中,您只需在数据库中查找该项目的存在。所有这些看起来都不错。但问题是你的show——你不需要这个代码changeset = Clients.change_work_item(%BudgetItem{project_id: project.id})——只需要用你的BudgetItem来呈现一个变更集,如下所示:changeset = Clients.change_work(%BudgetItem{})。现在,在您尚未发布的与此相关的控制器的发布操作中,您可以使用发送给控制器的id来查找项目并使用build_assoc创建关联的工作项。如果您可以在post-controller和Clients上下文中发送代码,那么会更容易提供帮助。

最新更新