Assigning variables inside map

I am creating a factory for a struct Cat where one key’s value is another key’s lowercase value.

Example

def cat_factory(attrs \\ %{}) do
 Cat%{
    name: cat_name = attrs[:name] || Faker.Cat.name(),
    cat_name_lowercase: cat_name |> String.downcase()
  }
end

This doesn’t seem to work. I get an error: undefined function cat_name/0. Any suggestions on how we could achieve this?

def cat_factory(attrs \\ %{}) do
  cat_name = attrs[:name] || Faker.Cat.name()
  Cat%{
    name: cat_name,
    cat_name_lowercase: cat_name |> String.downcase()
  }
end

:point_up: Why not this?

1 Like

Storing a calculated field seems to be a little bit inefficient… You can refine the display of Cat, but if You persist this in the db, it will be a waste of space.

1 Like

thank you for this solution

Is there a way to do this in ecto database level? One of my other fields cat_story_count requires to count the cat_story (which is paragraphs with sentences).

Postgres 12 has GENERATED COLUMNS, it’s a column that’s computed from another column, you should then be able to use it as a normal column in Ecto. Otherwise you can also compute it when fetching:

Cat
|> where([c], c.id == 42)
|> select([c], %{name: c.name, display_name: String.downcase(c.name)})
1 Like