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
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
users_current_location instead of
location. If you wanted to use
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
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
option for the
fieldmacro. It defaults to
fn 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
@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!