Box type in Ecto Schema

I have a box type in my postgres database, which i’m trying to map to my schema. I saw that Postgrex have a Postgrex.Extensions.Box, and tried to include it as follows:

config :my_app, MyApp.Repo,
  adapter: Ecto.Adapters.Postgres,
  extensions: [Postgrex.Extensions.Box],
  ...

and the use it

schema "foobar" do
   field :bounding_box, :box
   # ...
end

but with no luck.

** (ArgumentError) invalid or unknown type :box for field :bounding_box

Tried multiple variants of the type, e.g {:array, %Postgrex.Box{}} which includes the struct, but no luck there as well.

Any help appreciated!

1 Like

There is Postgrex Extension doc here.

I am not sure if it can compare… but I used postgis extension lately. To make it work, I added a lib/postgres_types.ex

Postgrex.Types.define(LabDb.PostgresTypes, [Geo.PostGIS.Extension] ++ Ecto.Adapters.Postgres.extensions(), json: Poison)

and changed repo config like that.

config :lab_db, LabDb.Repo,
  ...
  types: LabDb.PostgresTypes

I was then able to use specific type in my schema…

field :geom, Geo.Point

1 Like

Thanks for the reply!

I have added the type, and can now see that the extension is now being loaded, great!
But i’m still having some trouble defining the type.

field :bounding_box, Postgrex.Extensions.Box
# or
field :bounding_box, Postgrex.Box
# or
field :bounding_box, :box

is not working for me. All gives me the unknown or invalid type error. Looking at the source code, it seems like there might not be a type defined?

1 Like

I’m not sure if you know it, but maybe you can look at how geo does work: https://github.com/bryanjos/geo

1 Like

Ecto types and postgrex extensions are two separate things. You need both.

2 Likes

Thanks for the reply!

So i need to define a box type using the Ecto.Type behaviour, making use of %Postgrex.Box{} struct as my data structure?

1 Like

Yes, exactly. Sorry for making my last comment so brief.

To use a Postgres data type in Ecto that is not supported out of the box, you need two things:

  • a postgrex extension - this is defined by the Postgrex.Extension behaviour. It is responsible for low-level concerns like encoding and decoding the data from the wire format when communicating directly with the database.
  • an ecto type - this is defined by the Ecto.Type behaviour. It is responsible for higher-level features like casting and converting from application data format to raw database format (it might happen they are the same).

To use all of this, you need to define a custom postgrex type module using the custom extension and pass it as configuration to repo. This makes sure we can properly communicate with database. To use this type in the schema, the field declaration needs to use the newly defined ecto type.

3 Likes

Thank you, that did the trick!

1 Like