【问题标题】:cond and pattern matching against map针对地图的条件和模式匹配
【发布时间】:2017-08-19 23:17:44
【问题描述】:

在 phoenix 应用程序中,当用户提交特定表单时,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}

我实际上做了一个长期不好看的 if else if .... 声明来实现这一点。

有没有更好的灵丹妙药方法来做到这一点?

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    您可以使用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
    

    【讨论】:

    • 太好了,我不知道get_field,这似乎也是一个很酷的选择!
    【解决方案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
    

    代码未经测试,可能包含类型,但我希望你能明白。

    【讨论】:

    • 写完我的问题后,我发现这是我迄今为止尚未测试过的选项。我现在正在尝试,我会回复你!
    猜你喜欢
    • 2016-01-19
    • 2013-09-06
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 2017-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多