Elixir 监护人文件don';t让我生成JWT令牌

Elixir 监护人文件don';t让我生成JWT令牌,elixir,token,phoenix-framework,guardian,Elixir,Token,Phoenix Framework,Guardian,我正在使用{:guardian,“~>1.0”}为我的项目生成一个令牌,但它给了我一个错误 这是我的监护人档案的密码 defmodule Dailyploy.Guardian do use Guardian, otp_app: :dailyploy def subject_for_token(user, _claims) do sub = to_string(user.id) {:ok, sub} end def subject_for_token(_, _)

我正在使用{:guardian,“~>1.0”}为我的项目生成一个令牌,但它给了我一个错误

这是我的监护人档案的密码

defmodule Dailyploy.Guardian do
  use Guardian, otp_app: :dailyploy

  def subject_for_token(user, _claims) do
    sub = to_string(user.id)
    {:ok, sub}
  end

  def subject_for_token(_, _) do
    {:error, :reason_for_error}
  end

  def resource_from_claims(claims) do
    id = claims["sub"]
    resource = Dailyploy.Accounts.get_user!(id)
    {:ok,  resource}
  end

  def resource_from_claims(_claims) do
    {:error, :reason_for_error}
  end
end
它向我显示了一个错误,主题为。 此子句无法匹配,因为第4行的前一个子句始终匹配ESELIxir


有人能解释一下它为什么不起作用吗?

编译器正在抱怨,因为您对令牌的
subject\u的两个定义是相同的,它们都需要完全相同的参数

要解决此问题,请明确表示您希望在第一个定义中接收
User
struct:

  def subject_for_token(%User{id: id}, _claims) do
    {:ok, to_string(id)}
  end

  def subject_for_token(_, _) do
    {:error, :reason_for_error}
  end
  def go(_x, _y) do
    IO.puts "I must have matched the function call."
  end
  def go(_, _) do
    IO.puts "I will never match"
  end
这同样适用于索赔中的资源;这两个函数将匹配完全相同的参数。这也是可以解决的:

  def resource_from_claims(%{"sub" => sub}) do
    resource = Dailyploy.Accounts.get_user!(sub)
    {:ok, resource}
  end

  def resource_from_claims(_claims) do
    {:error, :reason_for_error}
  end
有人能解释一下为什么不起作用吗

调用函数时,elixir从定义中的第一个函数子句开始,并尝试将函数调用中指定的参数与函数定义中的参数匹配。如果没有匹配项,elixir将尝试下一个function子句。当找到匹配项时,将执行相应的函数体。如果所有函数子句都不匹配,则会出现函数\子句错误

让我们看一个例子。如果你写:

def go({1, 2}, :cat) do
   IO.puts "I must have matched the function call."
end
然后您可以这样调用该函数:

iex(2)> A.go({1, 2}, :cat)
I must have matched the function call.
:ok
  def go(_x, _y) do
    IO.puts "I must have matched the function call."
  end
但是,如果您尝试:

ex(3)> A.go("hello", 10)
** (FunctionClauseError) no function clause matching in A.go/2    

    The following arguments were given to A.go/2:

        # 1
        "hello"

        # 2
        10

    a.ex:2: A.go/2
由于定义
go()
的函数子句与函数调用不匹配,因此出现函数子句错误:

  function call:     A.go("hello", 10)
                            |       |
            {1,2} = "hello  |       | :cat = 10
                            V       V
  function def:    def go({1, 2}, :cat) do
go()
函数调用中唯一可以匹配函数定义中tuple
{1,2}
的参数是tuple
{1,2}
,函数调用中唯一可以匹配函数定义中atom
:cat
的参数是atom
:cat

但是,函数定义中的变量与任何内容都匹配。法定变量名的一些示例有:
x
y
\ux
\ucode>。因此,如果您这样定义
go()

iex(2)> A.go({1, 2}, :cat)
I must have matched the function call.
:ok
  def go(_x, _y) do
    IO.puts "I must have matched the function call."
  end
然后两个函数调用将匹配:

iex(3)> c "a.ex"          
warning: redefining module A (current version defined in memory)
  a.ex:1
[A]

iex(4)> A.go("hello", 10)
I must have matched the function call.
:ok

iex(5)> A.go({1, 2}, :cat)
I must have matched the function call.
:ok
如果在go()定义中添加第二个function子句:

  def subject_for_token(%User{id: id}, _claims) do
    {:ok, to_string(id)}
  end

  def subject_for_token(_, _) do
    {:error, :reason_for_error}
  end
  def go(_x, _y) do
    IO.puts "I must have matched the function call."
  end
  def go(_, _) do
    IO.puts "I will never match"
  end
第一个function子句仍将匹配任意两个参数,因此第二个function子句将永远不会执行——因此编译器会向您发出警告,这相当于:

Wtf?你为什么在第二个function子句中乱涂乱画 当它永远不会匹配,因此永远不会执行?!抓紧

当您在函数定义中进行模式匹配时,事情会变得有点棘手,例如:

def go(%{a: val}=map, x) do

请参阅以了解其工作原理。

{resource:“/home/shweta/dailyploy/lib/guardian.ex”,“message:“**(CompileError)lib/guardian.ex:4:User.\uu结构\uuuu/0未定义,无法展开结构用户\n lib/guardian.ex:4:(模块)\n”,}我假设您的应用程序中有一个要在此处使用的
用户
架构。如果是这样,请将其更改为您正在使用的确切用户模块,如
Dailyploy.Accounts.User
。将其更改为您正在使用的确切用户模块,如Dailyploy.Accounts.User-,或者包括以下行:
别名Dailyploy.Accounts.User
,这将使
%User{}
等同于
%Dailyploy.Accounts.User{/code>