Just match on params and use Access behaviour and syntax:
This will have the culprit though, that your action is called even when not all params are filled in and you have to manually check in the functions body. So in my opinion, matching them all in the head is the better way.
Just wanted to add an example on how expat could help in situations like yours - matching big structures, sorry if that’s not what you meant with better way.
use Expat
# You might want to split the pattern into the
# pieces that fit your domain.
# In these examples `m_` stands for Map
defpat m_auth(%{"AccountSid"=> account_sid,
"ApiVersion"=> api_version})
defpat m_from(%{"From"=> from,
"FromCity"=> from_city,
"FromCountry"=> from_country,
"FromState"=> from_state,
"FromZip"=> from_zip})
defpat m_body(%{"Body" => body))
defpat index_params(m_auth() = m_from() = m_body())
# The following will expand to your whole pattern,
# as you had in your original code, also if any
# named pattern had a guard, it would be expanded
# properly as part of `def index`.
def index(conn, params = index_params()) do
# Code here will only be executed if the params
# matched your whole pattern. So it's safe.
# You can also use your patterns in here
# in order to extract some values you are
# interested to work with:
m_from(from_country: country) = params
IO.puts("Got request from country #{country}")
...
end
Still new to Elixir so it’s gonna take me the weekend to evaluate all of these suggestions and see if it fits with our current understanding of the language and framework.
I do like the explicitness of the massive map, but it’s just unsightly. And Expat looks really useful.
I like the way it’s done in the Elixir codebase itself, for instance:
Stuff that really needs to be matched in the function head (due to overloads) is matched in the head; other stuff is matched on a separate line. If it gets too long you can just use two or three lines.
As a plus the error message when there’s a match error is easier to follow with this approach.