【问题标题】:Url to accept string instead of Id with spaces接受字符串而不是带空格的 Id 的 URL
【发布时间】:2016-07-13 07:18:43
【问题描述】:

以前有人问过这个问题,我什至回答了right here。 但是随着升级到 1.1.2,这种方法不再有效。由于名称中的任何空格(例如“Super Cleaner”)现在都表示为“Super+Cleaner”,这是传递给查询的值,因此不会收到任何命中。这样做的正确方法是什么?我认为这与 Valim 在另一篇文章中回答的 Phoenix.Param 有关吗?问题归结为它被视为整数而不是字符串,我不知道为什么。

怎么样: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

我的问题是武器名称现在的值为“Super+Cleaner”,使得查询没有返回结果。

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    对此的一般解决方案是结合您和 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,我们需要调整控制器中的查询,以便显示/编辑/更新/删除操作以按名称而不是 ID 获取武器:

    # web/controllers/weapon_controller.ex
    
    weapon = Repo.get_by!(Weapon, name: name)
    

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

    【讨论】:

    • 在这里向 Phoenix 提交了一个错误:github.com/phoenixframework/phoenix/issues/1616
    • 感谢您的回复,我不得不承认我仍然不确定 Param 如何帮助我,因为我对 Phoenix 和 Elixir 还很陌生。我想我是在错误地接近它,因为我在 HTML 中手动发送名称而不是通过内置的 Phoenix 函数?我不是故意使用这些资源,因为我只想得到。我更新了我的评论以包含代码。感谢您的精彩回复:)
    • 嘿@Wobbley,你所做的看起来非常好。您可以使用resourcesonly: [:get] 选项实现相同的效果,但这只是一个方便的包装器来做同样的事情。当您在视图中呈现 URL 时,params 协议很重要。例如。当您生成武器“显示”页面的链接时,您调用weapon_path(@conn, :show, weapon),然后phoenix 使用params 协议来确定将武器的哪个属性放在url 的末尾。
    • PR 出来了,希望能尽快解决 ;-) github.com/phoenixframework/phoenix/pull/1617
    • 我明白了,我想我应该创建一个基于名称检索的“默认”方法,而不是我创建的“自定义”方法。感谢您的 PR :)
    猜你喜欢
    • 1970-01-01
    • 2021-10-30
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 2016-08-20
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多