【问题标题】:Elixir check if string is integer in guardElixir检查字符串是否为整数
【发布时间】:2022-04-08 11:26:58
【问题描述】:

是否可以检查传入的字符串参数是否为整数?例如,我需要根据其 id ("12345") 或 external_id ("eUv9wWzZ48bMZsuII6ivCle2NHgIEPoMLWC9ioDV") 检索模型。这有可能实现吗?我尝试了is_integer,但它返回 false,因为它不尝试解析字符串。

def call(%{params: %{"id" => id}} = conn, module) when is_atom(module) and is_integer(id) do
    ZB.Repo.get!(module, id)
  |> check(conn)
end
def call(%{params: %{"id" => id}} = conn, module) when is_atom(module) do
  ZB.Repo.get_by!(module, external_id: id)
end

【问题讨论】:

  • 你应该选择@mudasobwa 的答案而不是我的;正如他解释的那样,我的不正确。 :)
  • @Dogbert 老实说,你的回答完全正确,回答了 陈述 :)

标签: elixir


【解决方案1】:

这是XY problem,我相信您正试图以不正确的方式解决不存在的问题:)

根据我从您的输入中看到的,external_id 应该是长度为 40 的字母数字字符串。这里的关键字是 alphanumeric。也就是说,40 次“1”可能是external_id。你知道吗?被Integer.parse/2完美解析:

iex|1 ▶ ["1"] |> List.duplicate(40) |> Enum.join |> Integer.parse
#⇒ {1111111111111111111111111111111111111111, ""}

也就是说,在这种情况下检查整数是无效,因为它可能会导致误报

你真正需要做的是尝试通过external_id获取记录,可能基于它的长度或其他东西,如果不成功则回退到id。此外,二进制的长度可能确实在保护中检查(隐含地,通过引入中间包装二进制⇒位串。)

def call(%{params: %{"id" => id}} = conn, module) when is_atom(module) do
  case ZB.Repo.get_by(module, external_id: id) do
    {:ok, record} -> record
    _ -> ZB.Repo.get!(module, id) |> check(conn)
  end
end

【讨论】:

    【解决方案2】:

    不,这不能在警卫中完成。您可以在警卫中调用的函数是有限的,并且不包括任何检查字符串是否仅包含数字的函数。

    您可以改为在正文中使用Integer.parse/1

    def call(%{params: %{"id" => id}} = conn, module) when is_atom(module) do
      case Integer.parse(id) do
        {_, ""} -> 
          ZB.Repo.get!(module, id) |> check(conn)
        
        _ -> 
          ZB.Repo.get_by!(module, external_id: id)
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-18
      • 2020-01-27
      • 2012-04-27
      • 1970-01-01
      • 1970-01-01
      • 2011-03-23
      • 2017-11-28
      相关资源
      最近更新 更多