sezaru
Use Ecto schema directly or convert to a custom struct?
Hello,
I have a question that probably is somewhat opinion-based.
Basically, when you have a schema for some persisted data in your database, do you use it directly in your code or do you convert it to another struct first?
Example
Say, I have a table to store financial data:
schema "candles" do
field :timestamp, :utc_datetime_usec
field :open, :decimal
field :close, :decimal
field :high, :decimal
field :low, :decimal
field :volume, :decimal
end
It’s typespec would be like this:
@type t :: %__MODULE__{
__meta__: Ecto.Schema.Metadata.t(),
id: integer | nil,
timestamp: DateTime.t() | nil,
open: Decimal.t() | nil,
close: Decimal.t() | nil,
high: Decimal.t() | nil,
low: Decimal.t() | nil,
volume: Decimal.t() | nil
}
Normally what I do is create a struct like this in another module:
defmodule Candle do
defstruct [:timestamp, :open, :close, :high, :low, :volume]
end
And whenever I read from the database, I always convert from the schema to the struct I created, and that struct is what is used in the rest of the program.
Do you think this is necessary or just a waste of CPU cycles? Can you see any advantages/disadvantages from each approach?
Most Liked
Adzz
Great question. This is similar to many discussions i’ve had at work in a few teams.
On the surface it seems like that would be extra work for not much gain. Especially as ecto is super flexible, allowing us to define a schema that only use some of the fields on the table, and allowing virtual fields.
However, I too use this approach, with one adjustment; I make the structs embedded schemas so all of them are ecto structs.
Why? So that i have a clear separation between business logic and the database.
I took a while to get used to the approach, it’s not necessary for every application, it adds some overhead.
But if you do it well where the data is stored is an implementation detail, allowing you yo easily pull things out and move them around without touching the domain logic.
I could have domain fields made from several db tables or even from different APIs.
That kind of approach is taking influence from DDD and hexagonal architecture, so could be more pros / cons in that literature.
al2o3cr
You’ve described what you’re doing, but not why. What advantage were you aiming for when setting up this pattern?
IMO this feels like boilerplate: you’re literally winding up with the same maps modulo a couple keys.
If you were feeling really fancy you could even do it with key-tweaking:
%CandleSchema{timestamp: ..., etc etc}
|> Map.from_struct()
|> Map.drop([:__meta__])
|> struct!(Candle)
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








