Sergio Tapia
Sergio Tapia

Reputation: 9823

Old ecto migration failing to run because I added a new field to model schema

I have an old migration that updates the roles for a user in the roles array field.

This migration doesn't run anymore because today I added a field called is_bot to my schema.

Here's what my migration looks like:

def up do
  query =
    from(
      u in "users",
      select: %{id: u.id, email: u.email, onboarded: u.onboarded, roles: u.roles}
    )

  Repo.transaction(
    fn ->
      query
      |> Repo.stream()
      |> Stream.each(fn user ->
        cond do
          user.onboarded && user.roles != nil && length(user.roles) > 1 ->
            roles = ["test"]

            user
            |> Repo.update_all(set: [roles: roles])

          true ->
            IO.puts("User #{user.email} has no roles. Onboarded: #{user.onboarded}")
        end
      end)
      |> Stream.run()
    end,
    timeout: :infinity
  )
end

And my schema:

schema "users" do
  field(:email, :string)
  field(:roles, {:array, :string})
  field(:onboarded, :boolean, default: false)
  field(:is_bot, :boolean, default: false)
end

I thought by using a u in "users", I would avoid going through my schema in my model, but it seems to be using it regardless.

Error:

** (Postgrex.Error) ERROR 42703 (undefined_column): column u0.is_bot does not exist
(db_connection) lib/db_connection.ex:1406: DBConnection.prepare_declare/4
(elixir) lib/stream.ex:1270: anonymous fn/5 in Stream.resource/3
(elixir) lib/stream.ex:1433: Enumerable.Stream.do_each/4
(elixir) lib/stream.ex:806: Stream.do_transform/8
(elixir) lib/stream.ex:1433: Enumerable.Stream.do_each/4
(elixir) lib/stream.ex:591: Stream.run/1
(ecto) lib/ecto/adapters/sql.ex:576: anonymous fn/3 in Ecto.Adapters.SQL.do_transaction/3
(db_connection) lib/db_connection.ex:1275: DBConnection.transaction_run/4

How can I run this migration?

Upvotes: 0

Views: 339

Answers (1)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

You are abusing migrations for running seeds. What you probably should do, is to move the seeding code somewhere into seeds/update_roles.exs and use this alias for setting ecto up (in mix.exs file):

defp aliases do
  [
    "ecto.setup": ["ecto.create", "ecto.migrate", "run seeds/update_roles.exs"],
    ...

That way the database would be first completely setup to the modern version and then seeded with the data. Current code tries to use the schema which contains is_bot field to run the seed on the database that does not yet contain it.

Upvotes: 2

Related Questions