coding addicted
coding addicted

Reputation: 3430

cond and pattern matching against map

In a phoenix app, when a user submit a specific form, lat and lng are calculated from address.

The lat and lng can be in changeset.data if no changes are made and in changeset.changes if changes are submit.

I perform other stuff on lat and lng on the changeset but I need to know where the coordinates are. What I'm trying to do is:

cond do 
  # Always use new coordinates if possible
  %{lat: lat, lng: lng} = changeset.changes ->
    do_something(lat, lng)
  %{lat: lat, lng: lng} = changeset.data ->
    do_something(lat, lng)
  true ->
    do_nothing_and_return_the_changeset_as_is
end

Of course this is not working because it's not returning true or false on pattern not matching.

** (MatchError) no match of right hand side value: %{lat: any_value}

I actually made a long not looking good if else if .... statement to achieved this.

Is there a better elixir way of doing this?

Upvotes: 4

Views: 2330

Answers (2)

Dogbert
Dogbert

Reputation: 222148

You can use case to match on the lat and lng inside changes or data:

case changeset do
  %{changes: %{lat: lat, lng: lng}} -> ...
  %{data: %{lat: lat, lng: lng}} -> ...
  _ -> ...
end

But, there's a better way: Ecto has a get_field function which handles getting the field value from changes, automatically falling back to data.

lat = get_field(changeset, :lat)
lng = get_field(changeset, :lng)
if lat && lng do
  ...
else
  ...
end

Upvotes: 2

Pfitz
Pfitz

Reputation: 7344

You could use pattern matching in functions like this:

...
# call do_something with the changeset
changset |> do_something()

#pattern match for lat,lng inside the changes
def do_something(%Ecto.Changeset{changes: {lat: lat, lng: lng}}) do
  ..
end

# pattern match for lat,lng inside data
def do_something(%Ecto_.Changeset{data: {lat: lat, lng: lng}}) do
  ..
end

# pattern match if no lat und lng are available !!! the order of the functions matters !!!
def do_something(%Ecto_Changeset{} = cs) do
  cs
end

Code is untested and may include types but I hope you will get the idea.

Upvotes: 2

Related Questions