Почему Postgrex - Ecto выдает эту ошибку not_null_violation?

ошибка

Вот ошибка, с которой я столкнулся при тестировании набора изменений моей учетной записи. Кажется, что это будет вызвано только миграцией Ecto с неправильно структурированной базой данных, но ecto.migrate работает нормально, также Postgresql не выдает никакой ошибки, когда я пытаюсь вставить строку, используя подобный набор изменений ниже.

** (Postgrex.Error) ERROR 23502 (not_null_violation): null value in column "email" violates not-null constraint

     table: accounts
     column: email

 Failing row contains (118, 66168645856, 1, 2018-08-17 03:19:12.176247, 2018-08-17 03:19:12.17626, null, null, null, null).
 code: account = insert(:account)
 stacktrace:
   (ecto) lib/ecto/adapters/sql.ex:554: Ecto.Adapters.SQL.struct/8
   (ecto) lib/ecto/repo/schema.ex:547: Ecto.Repo.Schema.apply/4
   (ecto) lib/ecto/repo/schema.ex:213: anonymous fn/14 in Ecto.Repo.Schema.do_insert/4
   (ecto) lib/ecto/repo/schema.ex:125: Ecto.Repo.Schema.insert!/4
   test/schema/account_test.exs:26: (test)

Экто миграции

migration_create_account.ex

def change do
    create table(:accounts) do
        add :phone_number, :string
        add :access_level, :integer

        timestamps()
    end
end

migration_add_account.ex

def change do
    alter table(:accounts) do
        add :email, :string
        add :auth_token, :string
        add :auth_token_expires_at, :utc_datetime
        add :signed_in_at, :utc_datetime
    end

    create unique_index(:accounts, :email, where: "email IS NOT NULL")
    create unique_index(:accounts, [:phone_number], where: "phone_number IS NOT NULL")
end

из машины

factory.ex

def account_factory do
    random_mobile_number = Enum.map(0..10, fn _i -> :rand.uniform(9) end)
    |> List.foldl("", fn i, acc -> acc <> "#{i}" end)

    %Account{
      phone_number: random_mobile_number,
      access_level: 1
    }
end

ExUnit

account_test.exs

describe "Account.changeset/2" do
   test "should check for valid phone number" do
     account          = insert(:account)
     negative_number  = %{phone_number: "-123233239" }
     refute changeset(account, negative_number).valid?
   end
end

Экто схема и ревизия

schema "accounts" do
    field :email       , :string
    field :phone_number, :string
    field :access_level     , :integer
    field :access_level_text, :string, virtual: true
    field :auth_token           , :string
    field :auth_token_expires_at, :naive_datetime
    field :signed_in_at         , :naive_datetime

    timestamps()
end

@required_params ~w(phone_number email access_level access_level_text)
def changeset(account, attrs) do
  account
  |> cast(attrs, @required_params)
  |> cast_access_level_text()
  |> validate_required([:access_level])
  |> validate_required_contact_handle()
  |> validate_number(:access_level, less_than: 3, greater_than: 0)
  |> validate_subset(:access_level_text, @access_levels)
  |> validate_format(:email, @email_regex)
  |> validate_format(:phone_number, @phone_number_regex)
  |> unique_constraint(:phone_number)
end

1 ответ

Спасибо, парни. Что произошло в моем случае, так это потому, что я изменил миграции после использования ecto.migrate, так что изменения миграции различаются между тестовой базой данных и базой данных разработки.

Я только что побежал MIX_ENV=test mix ecto.reset синхронизировать базу данных между средами.

Другие вопросы по тегам