cond和模式匹配地图

时间:2017-08-19 13:35:23

标签: elixir phoenix-framework

在凤凰应用中,当用户提交特定表单时,lat和lng是根据地址计算的。

如果没有进行任何更改,则lat和lng可以在changeset.data中;如果提交了更改,则可以在changeset.changes中。

我在转换集上执行lat和lng上的其他内容,但我需要知道坐标的位置。我想做的是:

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

当然这不起作用,因为它没有在模式不匹配时返回truefalse

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

我实际上做了很长时间没有好看,如果....声明来实现这个。

有没有更好的灵丹妙药这样做?

2 个答案:

答案 0 :(得分:2)

你可以在这样的函数中使用模式匹配:

...
# 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

代码未经测试,可能包含类型,但我希望您能理解。

答案 1 :(得分:2)

您可以使用case匹配latlng内的changesdata

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

但是,有更好的方法:Ecto有一个get_field函数,用于处理从changes获取字段值,自动回退到data

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