为什么Postgrex-Ecto抛出此not_null_violation错误?

时间:2018-08-17 03:35:52

标签: postgresql elixir ecto postgrex

错误

这是测试帐户变更集时遇到的错误。看来这仅是由于结构错误的数据库进行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)

Ecto迁移

  

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

ExMachina

  

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

Ecto模式和变更集

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 个答案:

答案 0 :(得分:0)

谢谢大家。在我的情况下发生的是,因为我在使用ecto.migrate之后更改了迁移,所以测试数据库和开发数据库之间的迁移更改有所不同。

我刚刚运行MIX_ENV=test mix ecto.reset在环境之间同步数据库。