10

私は Elixir と Phoenix Web フレームワークで遊んでいますが、今は外部キー制約を検証しようとして立ち往生しています。したがって、コメントの多いPostモデルが与えられた場合、次のようにモデルを記述しました。Comment

defmodule MyApp.Comment do
  use MyAPp.Web, :model

  schema "comments" do
    field :body, :text
    belongs_to :post, MyApp.Post

    timestamps
  end

  @required_fields ~w(body post_id)
  @optional_fields ~w()

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
    |> foreign_key_constraint(:post_id)
  end
end

およびその単体テスト:

defmodule MyApp.CommentTest do
  # [...]
  test "changeset with non existent post" do
    attrs = %{
      body: "A comment."
      post_id: -1 # some non-existent id?
    }
    refute Comment.changeset(%Comment{}, attrs).valid?
    assert {:post_id, "does not exist"} in errors_on(%Comment{}, %{})
  end
end

http://hexdocs.pm/ecto/Ecto.Changeset.html#foreign_key_constraint/3によると:

外部キー制約は、関連付けられたモデルが存在するかどうかをデータベースに依存してチェックすることによって機能します。これは、親もデータベースに存在する場合にのみ子が作成されることを保証するのに役立ちます。

私が書いたコードが機能することを期待していましたが、代わりに ( で定義されているように@required_fields ~w(body post_id)) 存在をチェックするだけです。私は何か間違ったことをしたか、ドキュメントのステートメントを誤解したことを除外していません。

誰かがすでにこれに出くわしましたか?

更新: 完全を期すために、移行は次のとおりです。

def change do
  create table(:comments) do
    add :body, :text
    add :post_id, references(:posts)

    timestamps
  end

  create index(:comments, [:post_id])
end
4

2 に答える 2

12

データベースに依存するため、マイグレーションで参照を追加し、実際のデータベース操作を行う必要があります。Repo.insert/1変更セットを呼び出すか、与える必要があります。Repo.update/1その後、 が返され{:error, changeset}ます。

Elixir にも Ecto にもオブジェクトがないことを思い出してください。したがってchangeset.valid?、データベース操作を実行することはできません。これは、実行する一連の変更を反映した単なるデータであり、挿入や更新などの操作を実行すると、このデータの状態が変化します。

最後に、errors_on/2これまでに作業してきたものではなく、常に新しい変更セットを返すことに注意してください。最後の行は次のようになります。

assert {:post_id, "does not exist"} in changeset.errors
于 2015-08-26T11:31:55.417 に答える
2

「データベースに依存する」とは、データベース モデルに FOREIGN KEY CONSTRAINT が必要であることを意味します。

移行では、次のようなものが必要でした。

create table(:comments) do
  add :post_id, references(:posts)
end

これにより、親テーブルと子テーブルの間で FOREIGN KEY CONSTRAINT CHECK が強制されます。

于 2015-08-25T13:24:16.383 に答える