2016-07-28 16 views
1

Lassen Sie uns sagen, ich habe ein Modell Post welche belongs_toCategory:Ecto - wie assoc_constraint den gleichen Fehler wie validate_required zurückgeben?

defmodule MyApp.Post do 
    use MyApp.Web, :model 

    schema "posts" do 
    field :title, :string 
    belongs_to :category, MyApp.Category 
    end 

    def changeset(model, params) do 
    model 
    |> cast(params, [:title, :category_id) 
    |> validate_required([:title, :category_id]) 
    |> assoc_constraint(:category) 
    end 
end 

Das Problem ist: Wenn ich params nicht category_id passieren zu, die changeset Fehler Schlüssel ist: category_id, aber auf assoc_constraint Ungültigkeits (falls Kategorie isn nicht vorhanden), habe ich category Schlüssel. Es ist ein bisschen kontraproduktiv für mich - weil das Problem eigentlich das gleiche ist - es gibt keine Kategorie für Post. Wie kann ich damit umgehen?

Antwort

0

Die einzige Möglichkeit dies zu tun, die ich nach dem Lesen von Ectos Quelle finden konnte ist, geben Sie den gewünschten Namen in das Feld als Fehler assoc_constraint, und überschreiben Sie dann die Constraint-Name selbst. Der Standardname für die Einschränkung "objects_to" lautet #{table name}_#{column in table}_fkey (source).

Edit: Wir könnten genauso gut foreign_key_constraint verwenden, wenn wir die :name vorbei sind wie wir selbst, das ist das einzige, was assoc_constraint tut das foreign_key_constraint nicht. Ich habe den folgenden Code aktualisiert.

Migration:

defmodule MyApp.Repo.Migrations.CreateComment do 
    use Ecto.Migration 

    def change do 
    create table(:comments) do 
     add :post_id, references(:posts, on_delete: :nothing) 
     timestamps() 
    end 
    create index(:comments, [:post_id]) 
    end 
end 

Modell:

def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:post_id]) 
    |> validate_required([:post_id]) 
    |> foreign_key_constraint(:post_id, name: :comments_post_id_fkey) 
end 

Demo:

iex(1)> Comment.changeset(%Comment{}, %{}).errors 
[post_id: {"can't be blank", []}] 
iex(2)> Comment.changeset(%Comment{}, %{post_id: 999}).errors 
[] 
iex(3)> {:error, changeset} = Comment.changeset(%Comment{}, %{post_id: 999}) |> Repo.insert; changeset.errors 
[post_id: {"does not exist", []}] 
iex(4)> Comment.changeset(%Comment{}, %{post_id: 1}) |> Repo.insert 
{:ok, 
%MyApp.Comment{__meta__: #Ecto.Schema.Metadata<:loaded, "comments">, 
    id: 1, inserted_at: #Ecto.DateTime<2016-07-29 06:25:24>, 
    post: #Ecto.Association.NotLoaded<association :post is not loaded>, 
    post_id: 1, updated_at: #Ecto.DateTime<2016-07-29 06:25:24>}}