Url 接受字符串而不是带空格的 Id

Url to accept string instead of Id with spaces

以前有人问过这个问题,我也回答过。 但是,升级到 1.1.2 后,此方法不再有效。由于名称中的任何 white-space,例如 "Super Cleaner" 现在表示为 "Super+Cleaner",这是传递给查询的值,因此没有收到任何匹配。这样做的正确方法是什么?我认为它与 Phoenix.Param 有关,正如 Valim 在另一个 post 中回答的那样?问题归结为它被视为整数而不是字符串,我不知道为什么。

怎么样:http://localhost:4000/weapons/Super+Cleaner

应该如何:http://localhost:4000/weapons/Super%20Cleaner

编辑:已更新以包含我的代码

HTML

<a class="secondary button" href="<%= weapon_path(@conn, :html_weapon_info, weapon.name) %>">Weapon Details</a>

路由器

get "/weapons/:weapon_name", WeaponController, :html_weapon_info

控制器

def html_weapon_info(conn, %{"weapon_name" => weapon_name}) do
  weapon = Repo.get_by(Weapon, name: weapon_name)
  ships = Weapon |> Weapon.get_ships(weapon_name) |> Repo.all
  render(conn, "weapon_show.html", weapon: weapon, ships: ships)
end

我的问题是 weapon_name 现在有值 "Super+Cleaner",使得查询 return 没有结果。

这个问题的一般解决方案是结合您的和 José 对您所链接问题的回答。快速回顾一下:

1。为您的模型实施 Phoenix.Param 协议

这会告诉 Phoenix 在为您的模型渲染 URL 时将哪个属性放入 URL。

# web/models/weapon.ex
defmodule MyApp.Weapon do
  # ...

  defimpl Phoenix.Param do
    def to_param(%{name: name}) do
      to_string(name)
    end
  end
end

2。调整路由器中的参数名称

这一步是可选的,但如果参数包含名称而不是 id,我认为应该这样调用。

# web/router.ex

resources "/weapons", WeaponController, param: "name"

3。调整控制器以通过新参数

获取记录

由于我们不再在 URL 中传递 ID,因此我们需要调整控制器中的查询,以便 show/edit/update/delete 操作通过名称而不是 ID 获取武器:

# web/controllers/weapon_controller.ex

weapon = Repo.get_by!(Weapon, name: name)

最后,空格的问题似乎是一个完全不同的问题。加号编码的空格来自 application/x-www-form-urlencoded 编码。然而,这种类型的编码仅在查询组件中有效,而不是 URL 本身的一部分。您完全正确地将空格编码为 %20 而不是这意味着您可能在 Phoenix 中发现了一个错误!