Retrospectively change ecto column data type

I created this schema with the :amount field being of type ‘float’. I now want it to be a decimal - so I have changed it and migrated the changes:

defmodule SpBank.Account.User do
  use Ecto.Schema
  import Ecto.Changeset
  alias SpBank.Account.Transaction
  schema "users" do
    # field :id 
    field :amount, :decimal
    field :name, :string
    has_many :transactions, Transaction 
    timestamps()
  end

  @doc false
  def changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :amount])
    |> validate_required([:name, :amount])
  end
end

However I am getting an error that amount is still a float when I try to insert 90 into the amount field:
# Postgrex expected a float, got #Decimal<90>. Please make sure the value you are passing matches the definition in your table or in your query or convert the value accordingly.

Why is this and how do I properly change the data taype of the column in the schema?

Unless your data is important, You can run…

mix ecto.reset

This will drop the database, recreate and migrate again under a Phoenix project.

Otherwise, the recommended way is to use a migration to alter a table.

Don’t forget to change the migration file and the schema :slight_smile:

1 Like

Ok I’ll try that thanks. FOr future reference, how would you migrate an alteration to this table so that the data type of the column changes as I already tried this but ecto.migrate returned an error for ‘no alter function found’?

SO I just reset the database and re-migrated it - still having the same error : Postgrex expected a float, got #Decimal<90>. Please make sure the value you are passing matches the definition in your table or in your query or convert the value accordingly.

Please show your migration file…

defmodule SpBank.Account.User do
  use Ecto.Schema
  import Ecto.Changeset
  alias SpBank.Account.Transaction
  schema "users" do
    # field :id 
    field :amount, :decimal
    field :name, :string
    has_many :transactions, Transaction 
    timestamps()
  end

  @doc false
  def changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :amount])
    |> validate_required([:name, :amount])
  end
end

alter table("users") do
  modify :amount, :decimal
end

let me know if you meant a different file, this is all new to me!

defmodule SpBank.Repo.Migrations.CreateUsers do
  use Ecto.Migration

  def change do
    create table(:users) do
      add :name, :string
      add :amount, :decimal

      timestamps()
    end

  end
end

The migration file is located in priv/repo/migrations and should be called create_users…

The db type should be :decimal, and the Elixir type should Decimal.

Sorry I put this comment just after my earlier one. It is showing the amount as ‘:decimal’, not float soo I am not sure why it seems to think it is a type float.

defmodule SpBank.Repo.Migrations.CreateUsers do
  use Ecto.Migration

  def change do
    create table(:users) do
      add :name, :string
      add :amount, :decimal

      timestamps()
    end

  end
end

Did You reset tables after update?

Ah for some reason when I tried ecto.reset this time, it actually worked - no idea why but thank you, much appreciated! :slight_smile: