我有一个locations
表,用于保存用户latitude
和longitude
。我正在使用带有扩展的Postgres/Postgis 13
来生成坐标。下面是我的型号:
schema "locations" do
field :latitude, :float
field :longitude, :float
field :context, :string
field :publish, :boolean
field :coordinates, Geo.PostGIS.Geometry
belongs_to(:user, User)
timestamps()
end
@doc false
def changeset(location, attrs) do
location
|> cast(attrs, [:user_id, :context, :longitude, :latitude, :publish])
|> validate_required([:user_id, :context, :longitude, :latitude])
|> cast_coordinates()
end
@spec cast_coordinates(Ecto.Changeset.t()) :: Ecto.Changeset.t()
def cast_coordinates(changeset) do
IO.inspect(changeset)
lat = get_change(changeset, :latitude)
lng = get_change(changeset, :longitude)
geo = %Geo.Point{coordinates: {lng, lat}, srid: 4326}
changeset |> put_change(:coordinates, geo)
end
当我create_location
:
def create_location(attrs \ %{}) do
IO.inspect(attrs)
%Location{}
|> Location.changeset(attrs)
|> Repo.insert()
end
一切顺利。cast_coordinates
中的changeset
为:
cast coordinate
#Ecto.Changeset<
action: nil,
changes: %{
context: "sss shop",
latitude: 38.115556,
longitude: 13.361389,
profile_id: 5,
publish: true,
user_id: 2
},
errors: [],
data: #OkBackend.Gis.ProfileLocation<>,
valid?: true
>
但当我update_location
:
def update_location(%Location{} = location, attrs) do
location
|> Location.changeset(attrs)
|> Repo.update()
end
不知怎的,我的cast_coordinate
抛出了argument error
,因为changeset
是:
#Ecto.Changeset<action: nil, changes: %{}, errors: [],
data: #OkBackend.Gis.ProfileLocation<>, valid?: true>
正如您所看到的,changes
内部什么都没有。
为什么?我该如何解决这个问题?
我认为这可能是因为在cast_coordinates
函数中,您使用的是get_change(changeset, :longitude)
。
这将为longitude
字段获得一个change
,但如果不更改字段,则它将返回nil
。
相反,您应该使用get_field(changeset, :longitude)
来获取更改后的经度,或者如果没有更改,则使用现有的经度,如下所示:
@spec cast_coordinates(Ecto.Changeset.t()) :: Ecto.Changeset.t()
def cast_coordinates(changeset) do
lat = get_field(changeset, :latitude)
lng = get_field(changeset, :longitude)
geo = %Geo.Point{coordinates: {lng, lat}, srid: 4326}
changeset |> put_change(:coordinates, geo)
end