Any good example in how field_source_mapper works in Ecto ?
This is my take on it, though I’ve never personally used it myself.
@field_source_mapper
allows for your schema field names to be different than your column names. For example, lets say you have:
schema "users" do
field :name, :string
field :location, :string
field :foo, :string
end
Ecto expects there to be a name
, location
, and foo
column on the source. You might be in a situation where you’re interfacing with an existing database that has already defined the columns names. The database might be using columns username
instead of name
, and users_current_location
instead of location
. If you wanted to use name
and location
in your schema, but still map them to the existing underlying columns then you could use a @field_source_mapper
for that. Something like:
@field_source_mapper fn
:name -> :username
:location -> :users_current_location
x -> x
end
It’s important to retain the default x -> x
mapping so that fields like foo
still map to the foo
column.
Nice !
I was thought that the mapper can be used to make transformations in the columns values too, is it possible right ? Because the mapper accepts functions so should be ok to apply a filter to a result.
The mapper is just for changing the columns names. It only receives the column name as an argument and is expected to return just a column name. From the docs:
In other words, it is a mechanism to automatically generate the
:source
option for thefield
macro. It defaults tofn x -> x end
, where no
field transformation is done;
And then the :source
option docs from the field macro:
:source
- Defines the name that is to be used in database for this field.
I guess I’m somewhat foolishly realizing that the way I used it in my previous example (mapping two of the fields directly) is better left for the :source
option like so:
schema "users" do
field :name, :string, [source: :username]
field :location, :string, [source: users_current_location]
field :foo, :string
end
The @field_source_mapper
seems more appropriate for when you want to map all columns names following a similar pattern. In fact, it looks like @field_source_mapper
will be ignored whenever :source
is set on the fields, seen here:
source = opts[:source] || Module.get_attribute(mod, :field_source_mapper).(name)
If you need to transform the data coming from the db take a look at Ecto.Type
Nice! This example really should be in the documentation!