Replace specific values in a struct with custom values

I have different structs returned from database and i want to replace the value Ecto.Assoication.Notloaded with some custom value like not loaded in all of them.

This is one record

 unit = %{
  __meta__: #Ecto.Schema.Metadata<:loaded, "units">,
  cdc_location_class_id: nil,
  description: "",
  facility: #Ecto.Association.NotLoaded<association :facility is not loaded>,
  facility_id: 2215,
  id: 719,
  is_active: true,
  name: "Unit",
  rooms: #Ecto.Association.NotLoaded<association :rooms is not loaded>
}

This is the map I want

 unit = %{
  __meta__: #Ecto.Schema.Metadata<:loaded, "units">,
  cdc_location_class_id: nil,
  description: "",
  facility: "not loaded">,
  facility_id: 2215,
  id: 719,
  is_active: true,
  name: "Unit",
  rooms: "not loaded"
}

Any suggestions?

Thanks

You can use Enum.map or :maps.map for it.

unit
|> Enum.map(fn
  {k, %Ecto.Association.NotLoaded{}} -> {k, "not loaded"}
  other -> other
end)
|> Enum.into(%{})

or

:maps.map(fn
  _k, %Ecto.Association.NotLoaded{} -> "not loaded"
  _k, v -> v
end, unit)
2 Likes

Try something like:

defp replace_not_loaded_value({k, %Ecto.Association.NotLoaded{}}) do
  {k, "not loaded"}
end

defp replace_not_loaded_value({k, v}), do: {k, v}

unit
|> Map.to_list()
|> Enum.map(&replace_not_loaded_value/1)
|> Enum.into(%{})
1 Like

You can try this too…

unit 
|> Enum.reduce(%{}, fn 
  {k, %Ecto.Association.NotLoaded{}}, acc -> Map.put(acc, k, "not loaded")
  {k, v}, acc -> Map.put(acc, k, v) 
end)

Each time I see a map … into, I feel reduce might do the same in one iteration. I did not benchmark, but this really is only one (ugly?) round trip.

2 Likes

Each time I see a map … into with a Map argument, I reach for Map.new

2 Likes