我在我的项目中使用{: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
它向我显示了一个subject_for_token的错误。 该子句无法匹配,因为第4行的前一个子句始终匹配Elixir
有人可以解释为什么它不起作用吗?
答案 0 :(得分:0)
编译器在抱怨,因为您对subject_for_token
的两个定义是相同的,它们都期望使用完全相同的参数。
要解决此问题,请明确表明要在第一个定义中接收User
结构:
def subject_for_token(%User{id: id}, _claims) do
{:ok, to_string(id)}
end
def subject_for_token(_, _) do
{:error, :reason_for_error}
end
关于resource_from_claims
也可以这样说;这两个函数将匹配完全相同的参数。这也可以解决:
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
答案 1 :(得分:0)
有人可以解释一下为什么这不起作用吗?
调用函数时,elixir以定义中的第一个函数子句开头,并尝试将函数调用中指定的参数与函数定义中的参数进行匹配。如果不匹配,则应长生不老药尝试下一个函数子句。找到匹配项后,将执行相应的功能主体。如果没有任何一个功能子句匹配,则将出现一个function_clause错误。
我们来看一个例子。如果您写:
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
但是,如果您尝试:
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()
函数调用中唯一可与函数定义中的元组{1, 2}
匹配的参数是元组{1, 2}
,而函数调用中唯一可与函数定义中的原子:cat
是原子:cat
。
但是,函数定义中的变量匹配任何东西。合法变量名称的一些示例为:x
,y
,_x
和_
。因此,如果您这样定义go()
:
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()定义中添加第二个函数子句:
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
第一个函数子句仍然会匹配任何两个参数,并且由于这种情况,第二个函数子句将永远不会执行-因此编译器会向您发出警告,等效于:
Wtf?为什么在第二个函数子句中乱涂所有垃圾 什么时候永远不会匹配,因此永远不会执行?抓紧时间!
在函数定义中进行模式匹配时,事情变得有些棘手,例如:
def go(%{a: val}=map, x) do
有关其工作原理,请参见here。