2016-04-05 18 views

Odpowiedz

43

A Little śledzić na Patryka odpowiedź

Korzystanie tworzyć tylko unique_index modelu ostatecznie wyjątek zamiast daje błąd.

Aby uzyskać błąd, należy dodać ograniczenie do zestawu zmian, ale jako paremeter można podać nazwę indeksu utworzoną przez unikalny_indeks.

Więc w pliku migracji:

create unique_index(:your_table, [:col1, :col2], name: :your_index_name) 

Następnie w changeset:

def changeset(model, param \\ :empty) do 
    model 
    |> cast(params, @required_fields, @optional_fields) 
    |> unique_constraint(:name_your_constraint, name: :your_index_name) 
end 
+0

To powinno być oznaczone jako zaakceptowana odpowiedź imo. @ TheSquad, does: name_your_constraint muszą być: col1 lub: col2 w tym kontekście? Odsyłacz: https://hexdocs.pm/ecto/Ecto.Changeset.html#unique_constraint/3 – Olshansk

+1

absolutnie nie, możesz umieścić dowolny atom, który chcesz mieć kompleksowy komunikat o błędzie, gdy ograniczenie nie jest spełnione – TheSquad

10

Można utworzyć unikatowy indeks w wielu rzędach z

create unique_index(:some_table, [:col1, :col2]) 

Przypuszczam, że jeśli chcesz mieć klucze kompozytowe, trzeba użyć execute/1 uruchomić SQL ręcznie. Nie mam pewności, jak dobrze klawisze kompozytowe działają z Ecto, ale ogólnie trzymam się standardowego identyfikatora seryjnego dla każdej tabeli.

Jeśli powinieneś pójść z podejściem złożonego klucza, myślę, że ograniczenia NOT NULL nie są konieczne. Klucz złożony powinien już wymuszać, że kolumny nie mają wartości NULL.

4

unique_index byłoby nie utworzyć kompozytowy klucz podstawowy, jak pokazano na przykład na pytanie za. Tworzy wyjątkowe ograniczenie.

Jeśli chcesz utworzyć kompozytowy klucz podstawowy (Uwaga: nie zaleca się podczas pracy z Ecto) there's more information here:

migracji:

defmodule HelloPhoenix.Repo.Migrations.CreatePlayer do 
    use Ecto.Migration 

    def change do 
    create table(:players, primary_key: false) do 
     add :first_name, :string, primary_key: true 
     add :last_name, :string, primary_key: true 
     add :position, :string 
     add :number, :integer 
     ... 

Schema:

defmodule HelloPhoenix.Player do 
    use Ecto.Schema 

    @primary_key false 
    schema "players" do 
    field :first_name, :string, primary_key: true 
    field :last_name, :string, primary_key: true 
    field :position, :string 
    field :number, :integer 
    ... 

W większości przypadków jest to jednak potrzebne.