Почему 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
синхронизировать базу данных между средами.