Ecto更新Location记录时cast_coordinates抛出参数错误的原因及解决
问题原因
- 你当前使用的
get_change/3函数仅会读取changeset.changes中存在的变更字段值,若字段没有发生变更,该函数返回nil - 更新场景下,如果用户没有修改
latitude或longitude,这两个字段不会出现在changes中,此时lat和lng均为nil,构造%Geo.Point{}时传入nil坐标就会触发参数错误 - 即便你只修改了其中一个坐标字段,另一个字段通过
get_change拿到的也是nil,同样会报错
解决方案
修改cast_coordinates函数的逻辑,优先读取变更值,没有变更就读取已有存储值,且仅在经纬度都有有效值时才更新坐标字段即可:
@spec cast_coordinates(Ecto.Changeset.t()) :: Ecto.Changeset.t() def cast_coordinates(changeset) do # 优先取变更值,没有变更则取已有存储值 lat = get_change(changeset, :latitude) || changeset.data.latitude lng = get_change(changeset, :longitude) || changeset.data.longitude # 只有经纬度都有有效值时才更新坐标字段 if is_number(lat) and is_number(lng) do geo = %Geo.Point{coordinates: {lng, lat}, srid: 4326} put_change(changeset, :coordinates, geo) else changeset end end
内容的提问来源于stack exchange,提问作者sooon
相关产品推荐
相关产品推荐

