Phoenix通过可选的“inputs_for”嵌套表单输入导致控制器中的映射未通过验证。例如,帖子有评论。如果我想在创建帖子时为帖子添加注释,嵌套表单将如下所示:
<%= form_for @changeset, @action, fn p -> %>
<%= text_input p, :body %>
<%= inputs_for p, :comments, fn c -> %>
<%= text_input c, :body %>
<% end %>
<% end %>
我填写帖子正文,但这次没有为评论添加任何内容。这将为我们提供
控制器中的params [“post”]地图%{
"body" => "My post",
%{"comments" => %{"0" => %{"body" => ""}}
}
但是,评论是“可选的”。因此,为注释完成的验证将失败,因为有一个正文但它是空的。
接下来的问题是,如果注释为空,我们如何删除/清除注释,但如果它有某些值,请保留它?擦除params“post”似乎没有成功。
答案 0 :(得分:1)
我想您必须编写自己的scrub_comments
function plug,这将从评论地图中删除空评论,并最终删除评论为空。
答案 1 :(得分:0)
这是克里斯提到的那种方法。以下内容是从我的工作版本修改而来的,可以处理帖子和评论,并且未经测试,但至少应显示该方法。
帮助程序模块:
defmodule MyappWeb.Helpers do
alias MyappWeb.Post
def filter_post_params(%Plug.Conn{:params => %{"post" => %{"comments" => _}}} = conn, _opts) do
filtered_params =
conn.params
|> get_in(["post"])
|> Enum.reject(fn({_, x}) -> match?(%{"comments" => nil}, x) end)
|> Enum.into(%{})
new_params = put_in(conn.params, ["post"], filtered_params)
%Plug.Conn{conn | params: new_params}
end
def filter_post_params(%Plug.Conn{} = conn, _opts), do: conn
end
控制器,使用Phoenix的scrub_params
插头和我们的filter_post_params
插头,从上方:
defmodule MyappWeb.PostController do
use MyappWeb, :controller
alias Myapp.Post
plug :scrub_params, "post" when action in [:create, :update]
plug :filter_post_params when action in [:create, :update]
# ...
end