Elixir/Phoenix 加一个。通过表格将实体关联到现有实体
Elixir/Phoenix add a. related entity to an existing one via form
我对 elixir/phoenix 很陌生,我对一个概念有点费劲。我找到了解决方法,但我对此并不满意。
上下文:
我在我的数据库中创建了一个“项目”。现在我想通过项目“显示”页面创建一个与项目相关的“工作项”。因为它与那个特定项目有关,所以我需要将 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 中数据的不可变性。我的解决方法是现在我在“存储”project_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{})
。现在,在与此相关的控制器的 post 操作上,您尚未 post 编辑,您可以使用发送到控制器的 ID 来查找项目并使用 [=13= 创建关联的工作项].如果您可以在 post 控制器和客户端上下文中发送您的代码,它可能会更容易提供帮助。
我对 elixir/phoenix 很陌生,我对一个概念有点费劲。我找到了解决方法,但我对此并不满意。
上下文: 我在我的数据库中创建了一个“项目”。现在我想通过项目“显示”页面创建一个与项目相关的“工作项”。因为它与那个特定项目有关,所以我需要将 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 中数据的不可变性。我的解决方法是现在我在“存储”project_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{})
。现在,在与此相关的控制器的 post 操作上,您尚未 post 编辑,您可以使用发送到控制器的 ID 来查找项目并使用 [=13= 创建关联的工作项].如果您可以在 post 控制器和客户端上下文中发送您的代码,它可能会更容易提供帮助。