如何解决phoenix-framework 与复选框的多对多关系在验证失败时引发参数错误
我正在学习 elixir 和 phoenix 框架,其中有一个应用程序可以添加房间。房间可能与停车和便利设施有 many-to-many
关系。停车和便利设施就像通过复选框检查的标签,除了那个房间有价格、地址、纬度、经度和其他字段。当我填写所有正确的值时,每件事都运行良好,空间就创造出来了。但抛出
当我检查停车或便利设施字段并将其他字段留空并提交时出现 ArgumentError。
Request: POST /rooms
** (exit) an exception was raised:
** (ArgumentError) lists in Phoenix.HTML and templates may only contain integers representing bytes,binaries or other lists,got invalid entry: #Ecto.Changeset<action: :update,changes: %{},errors: [],data: #Tailwind.Parkings.Parking<>,valid?: true>
这是验证失败时抛出的变更集。
Ecto.Changeset<
action: nil,changes: %{
amenities: [
#Ecto.Changeset<action: :update,data: #Tailwind.Amenities.Amenity<>,valid?: true>
],parkings: [
#Ecto.Changeset<action: :update,valid?: true>
]
},errors: [
address: {"can't be blank",[validation: :required]},price: {"can't be blank",number_of_rooms: {"can't be blank",lat: {"can't be blank",long: {"can't be blank",[validation: :required]}
],data: #Tailwind.Rooms.Room<>,valid?: false
>
我最好的猜测是变化中的便利设施和停车位值是问题的原因。不是简单的列表,而是在便利设施和停车场领域进行了更改。即使我的猜测是对的,我也没有足够的理解它为什么会这样以及它应该是怎样的。
def create_room(attrs \\ %{}) do
%room{}
|> Room.changeset(attrs)
|> put_parking_association(attrs["parkings"])
|> put_amenity_association(attrs["amenities"])
|> Repo.insert()
end
和 put_amenity_association 函数只是从 db 中获取具有该 id 的所有值并添加与它们的关联。
defp put_amenity_association(changeset,attrs) do
amenities = Tailwind.Amenities.get_amenities(attrs)
Ecto.Changeset.put_assoc(changeset,:amenities,amenities)
end
def get_amenities(ids) do
Repo.all(from a in Tailwind.Amenities.Amenity,where: a.id in ^ids)
end
我正在模板中渲染这样的表单。
<%= for amenity <- @amenities do %>
<div class="flex items-center py-2 sm:w-1/4">
<%= checkBox f,checked_value: amenity.id,hidden_input: false,name: "room[amenities][]",class: "h-5 w-5 focus:ring-gray-900 focus:ring-1 bg-gray-900 text-gray-600" %>
<span class="ml-3 text-sm"><%= amenity.name %></span>
<% end %>
<span class="text-red-600 px-2">
<%= error_tag f,:amenities %>
</span>
我为此苦恼了几天却没有任何结果,而且感觉没有方向。在这件事上一点阳光都会对前进有很大帮助。
更新:
使用已接受的解决方案,我将 create_room 函数更改如下:
def create_room(attrs \\ %{}) do
case Room.changeset(%room{},attrs) do
%Ecto.Changeset{valid?: false} = changes ->
changes
|> apply_action(:insert)
# |> Repo.insert()
changeset ->
changeset
|> put_parking_association(attrs["parkings"])
|> put_amenity_association(attrs["amenities"])
|> IO.inspect()
|> Repo.insert()
end
end
解决方法
如果缺少必填字段,Room.changeset(attrs)
会返回一个无效的变更集,该变更集不会被任何后续调用进一步修改(因为它已经无效。)
它被直接传递给 Repo.insert/2
返回 {:error,changeset}
。
所以你需要的可能是不仅要处理快乐路径,还要处理错误。
def create_room(attrs \\ %{}) do
case Room.changeset(%Room{},attrs) do
%Ecto.Changeset{valid?: false} -> handle_error(...)
changeset ->
changeset
|> put_parking_association(attrs["parking"])
|> put_amenity_association(attrs["amenities"])
|> Repo.insert()
end
...
您看到的错误可能是由堆栈向下引起的,但原因与上述相同。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。