LauraBeatris

LauraBeatris

How to apply a guard in a function

The goal of this post is to get some guidance on how to apply guards to the function below. I’m struggling to make it work with the when keyword, and had to place a giant if block to make the logic work.

Giving more context around the function: Either a ‘connection’, ‘organization’, ‘domain’, or ‘provider’ args should be provided, otherwise the function shouldn’t be executed.

This is how it looks like by using a if

 @doc """
  Generates an OAuth 2.0 authorization URL.
  """
  @spec get_authorization_url(map()) :: {:ok, String.t()} | {:error, String.t()}
  def get_authorization_url(params) do
    if is_map_key(params, :connection) or is_map_key(params, :organization) or
         is_map_key(params, :redirect_uri) do
      if is_map_key(params, :domain) do
        Logger.warn(
          "The `domain` parameter for `get_authorization_url` is deprecated. Please use `organization` instead."
        )
      end

      defaults = %{
        client_id: WorkOS.config() |> Keyword.take([:client_id]),
        response_type: "code"
      }

      query =
        defaults
        |> Map.merge(params)
        |> Map.take(
          [
            :domain,
            :provider,
            :connection,
            :organization,
            :client_id,
            :redirect_uri,
            :state,
            :domain_hint,
            :login_hint
          ] ++ Map.keys(defaults)
        )
        |> URI.encode_query()

      base_url = WorkOS.config() |> Keyword.take([:base_url])

      {:ok, "#{base_url}/sso/authorize?#{query}"}
    else
      {:error, "Invalid params"}
    end
  end

I tried to do the same approach with a guard:

 @spec get_authorization_url(map()) :: {:ok, String.t()} | {:error, String.t()}
  def get_authorization_url(params) when is_map_key(params, :connection) or is_map_key(params, :organization) or
         is_map_key(params, :redirect_uri) do
      if is_map_key(params, :domain) do
        Logger.warn(
          "The `domain` parameter for `get_authorization_url` is deprecated. Please use `organization` instead."
        )
      end

      defaults = %{
        client_id: WorkOS.config() |> Keyword.take([:client_id]),
        response_type: "code"
      }

      query =
        defaults
        |> Map.merge(params)
        |> Map.take(
          [
            :domain,
            :provider,
            :connection,
            :organization,
            :client_id,
            :redirect_uri,
            :state,
            :domain_hint,
            :login_hint
          ] ++ Map.keys(defaults)
        )
        |> URI.encode_query()

      base_url = WorkOS.config() |> Keyword.take([:base_url])

      "#{base_url}/sso/authorize?#{query}"
  end

However, I’m getting the following Dialyzer error: “The @spec for the function does not match the success typing of the function.” - what is it trying to infer here regarding the “does not match the success typing”?

Should another function clause be declared to handle the case where none of those args are provided?

Marked As Solved

stefan_z

stefan_z

Hi @LauraBeatris,

What I can see from your guard example is that you definitely miss default get_authorization_url /1 function that will be called when one of the guards is false.
def get_authorization_url(_params), do: {:error, "Invalid params"}

Also specification for a function says that return types are {:ok, String.t()} | {:error, String.t()} but your function only returns string instead of tuple.

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
LegitStack
I’m hoping you guys can give me some general advice and perhaps code examples if you’re feeling up to it. I’m very interested in Elixir,...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New

Other popular topics Top

dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 49522 488
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

We're in Beta

About us Mission Statement