我想重载一个函数,该函数将map作为几个不同情况的参数。调用函数时,将根据映射中的键执行不同的函数。
例如,在此find_user!()
函数中,我可以通过id
,email
或mobile
个数字字段找到用户,这些字段都在数据库中编入索引。
def find_user!(%{"id" => user_id}) do
Repo.get(User, user_id)
end
def find_user!(%{"email" => email}) do
IO.puts "get user by email"
Repo.get_by(User, email: email)
end
def find_user!(%{"mobile" => mobile}) do
IO.puts "get user by mobile"
Repo.get_by(User, mobile: mobile)
end
虽然,在这种情况下,我同时拥有email
和mobile
号码,我想使用提供的电子邮件在数据库中查找记录,如果找不到,请查找手机号码。如果两者都找不到,则应返回标准nil
或RecordNotFound异常。
def find_user!(%{"email" => email, "mobile" => mobile } = params) do
Enum.any?(params, fn(x,y) -> IO.puts "#{x} , #{y} " end )
#Try finding by Email, then try finding by mobile
# code goes here
end
我开始使用这些字段并开始尝试使用条件来Enum.any?
来测试是否对包含email
和mobile
的地图进行了检索,但在此之前我已经实现了当我在控制台中运行MyApplication.find_user!(%{ "email" => "admin@example.com","mobile" => "0009998888"})
函数时,重载转到第一个重载的find_user!(%{"email" => email})
函数而不是我的函数。我认为这是因为它首先与该领域匹配。
有没有办法用这样的参数映射重载Elixir中的函数?或者我是否接近这个问题?也许我应该使用递归样式函数来初始尝试查找记录,然后使用不同的属性重试。
答案 0 :(得分:2)
这是另一种方法,不需要在前三个函数中添加任何内容:
def find_user!(%{"id" => user_id}) do
Repo.get(User, user_id)
end
def find_user!(%{"email" => email} = params) do
IO.puts "get user by email, then mobile"
case Repo.get_by(User, email: email) do
nil -> Repo.get_by(User, mobile: params["mobile"])
val -> val
end
end
def find_user!(%{"mobile" => mobile}) do
IO.puts "get user by mobile"
Repo.get_by(User, mobile: mobile)
end