Как использовать библиотеку Geo для создания действительного набора изменений модели Ecto?

Я пытаюсь использовать библиотеку Geo для хранения Geo.Point через набор изменений модели Phoenix. Мои параметры: {coordinates: [49.44, 17.87]} или больше предпочитаю {coordinates: {latitude: 49.44, longitude: 17.87}}

В консоли iex я пробовал:

iex(5)> changeset = Place.changeset(%Place{}, %{coordinates: [49.44, 17.87]})
%Ecto.Changeset{action: nil, changes: %{}, constraints: [],
 errors: [coordinates: "is invalid"], filters: %{}
 model: %Myapp.Place{__meta__: #Ecto.Schema.Metadata<:built>,
  coordinates: nil, id: nil, inserted_at: nil, updated_at: nil}, optional: [],
 opts: [], params: %{"coordinates" => [49.445614899999995, 17.875574099999998]},
 repo: nil, required: [:coordinates],

Все остальные попытки заканчивались ошибками Poison.Parser.

Как должны выглядеть параметры со стороны клиента, чтобы создать действительный набор изменений?

Модель:

defmodule MyApp.Place do
  use MyApp.Web, :model

  schema "place" do
    field :coordinates, Geo.Point

    timestamps
  end

  @required_fields ~w(coordinates)
  @optional_fields ~w()

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end
end

person luzny    schedule 23.11.2015    source источник


Ответы (2)


По тестам для библиотеки:

https://github.com/bryanjos/geo/blob/351ee6c4f8ed24541c9c2908f615e7b0a238f010/test/geo/ecto_test.exs#L100

Вам нужно передать Geo.Point в вашу функцию набора изменений:

changeset = Place.changeset(%Place{}, %{coordinates: %Geo.Point{coordinates: {49.44, 17.87}})

Подробнее о настраиваемых типах экто можно прочитать в [документах].(https://hexdocs.pm/ecto/Ecto.Type.html#content)

person Gazler    schedule 23.11.2015
comment
Не могли бы вы сказать мне, как я могу сопоставить {coordinates: {latitude: 49.44, longitude: 17.87}}, чтобы извлечь latitude и longitude в %Geo.Point{} в правильном формате? - person luzny; 23.11.2015
comment
%Geo.Point(coordinates: {get_in(coords_map.coordinates.latitude), get_in(coords_map.coordinates.longitude)}) elixir-lang.org/docs/stable/elixir/Kernel .html#get_in/2 - person Gazler; 23.11.2015
comment
когда у меня есть больше параметров, таких как coords_map = %{name: "test", coordinates: %{latitude: 49.44, longitude: 17.87}}, я хотел бы объединить %Geo.Point с параметром координат, это какой-то простой способ? - person luzny; 23.11.2015
comment
coords_map = map.coordinates затем %Geo.Point(coordinates: {get_in(coords_map.latitude), get_in(coords_map.longitude)} - person Gazler; 23.11.2015
comment
Я не могу использовать get_in/2 внутреннее совпадение в контроллере, поэтому не могли бы вы сказать мне, могу ли я обернуть координаты %Geo.Point внутренним соответствием контроллера def create(conn, %{"notify" => notify_params}) do ? Я хочу передать и другие параметры. - person luzny; 24.11.2015
comment
@luzny Вы можете использовать параметры сопоставления с образцом. def create(conn, %{"notify" => %{"coordinates" => %{"longitute" => longitude, "latitide" => latitude}} = notify_params) Если это не имеет смысла или не решает вашу проблему, создайте новый вопрос, в котором более четко объясняется ваша проблема. - person Gazler; 24.11.2015

Для будущих читателей есть также geo_postgis того же автора, основанный на geo, который является постгрексом. расширение и работает с экто.

person Geoffroy    schedule 06.06.2019