Phoenix model : loaded virtual field

Hi guys,

I need to load dynamically a field from my model schema but i doesn’t find the good solution…
Indeed, when i use Poison.Encoder and virtual field it’s ok, the field “day_cellule” is loaded in my view.
(I use the function Myproject.Services.get_day_cellule(cellule.id) to load this cellule)

But when i request my model, “day_cellule” without encode function, this field is always :nil ! And i doesn’t find a solution.

My model :

defmodule Myproject.Cellule do

require Logger

use Myproject.Web, :model

schema “cellules” do

field :position, :integer
field :day_cellule, :map, virtual: true
timestamps()

end

def changeset(struct, params \ %{}) do
struct
|> cast(params, [:position])
|> validate_required([:position])
end

def encode_model(cellule) do
%Myproject.Cellule{cellule | day_cellule: Myproject.Services.get_day_cellule(cellule.id)}
end

defimpl Poison.Encoder, for: Myproject.Cellule do
def encode(cellule, options) do
cellule = Myproject.Cellule.encode_model(cellule)
Poison.Encoder.Map.encode(Map.take(cellule, [:id, :position, :day_cellule]), options)
end
end

end

How to do this ?

Thanks guys !

1 Like

A virtual field in an Ecto schema is simply not persisted to the database.
There is no automatic mechanism for populating them. Unless you explicitly set a value (like you do in your encode_model/2 function), they will always be nil.

If you are loading your data from another Schema, you might want to look into the functions Ecto provides for dealing with associations. Those can easily be loaded with Repo.preload/3 or a :preload statement in your query.
This blog article gives a nice overview over how to handle associations in Ecto schemas:

Alternatively, you can also find many examples for using associations in the documentation of Ecto.Schema, Ecto.Query Ecto.Repo.

Thanks to reply !

So, it’s not possible to call encode_model by defaut, for all requests? (without use preload mechanism)

it’s not possible because Ecto Schema, unlike an ORM class in an OOP language, is merely a description of the data structure.
If you want to modify or load the contents of that data structure, you’ll have explicitly do so somewhere else.