2016-04-19 16 views
6

Io uso Phoenix e Ecto in uno dei miei progetti.Come eseguire l'aggiornamento in migrazione per Ecto?

Desidero aggiungere una colonna a una tabella e mi aspetto che sia una colonna NOT NULL. Ma ho già alcuni dati esistenti, quindi decido di aggiungere la colonna, aggiornare tutte le righe con un certo valore e modificare la colonna in NOT NULL.

ho provato questi codice a due:

# solution 1 
    def up do 
    alter table(:channels) do 
     add :type, :integer 
     Exchat.Repo.update_all("channels", set: [type: 1]) 
     modify :type, :integer, null: false 
    end 
    end 

    # solution 2 
    def up do 
    alter table(:channels) do 
     add :type, :integer 
    end 
    Exchat.Repo.update_all("channels", set: [type: 1]) 
    alter table(:channels) do 
     modify :type, :integer, null: false 
    end 
    end 

Entrambi non ha funzionato ed ho ottenuto errore come:

23::40::07.514 [info] == Running Exchat.Repo.Migrations.AddTypeToChannels.up/0 forward 

23::40::07.541 [debug] UPDATE "channels" AS c0 SET "type" = $1 [1] ERROR query=12.0ms 
** (Postgrex.Error) ERROR (undefined_column): column "type" of relation "channels" does not exist 
    (ecto) lib/ecto/adapters/sql.ex:383: Ecto.Adapters.SQL.execute_and_cache/7 

non sono sicuro se è legato alla versione Ecto, ma la mia versione Ecto è 2.0.0-rc.0.

Esiste un modo per raggiungere questo obiettivo? O c'è qualcosa di sbagliato nel mio codice di esempio?

+2

Provate ad aggiungere 'flush()' dopo il primo 'alter do end' nella vostra soluzione # 2. Funziona? – Dogbert

+0

Funziona! Grazie! –

+0

Hm ... Lo stesso codice genera l'errore di argomento '** (ArgumentError)'. Cosa può essere sbagliato? gist - https://gist.github.com/maslenkov/1ca80dbc913f92a9334a6545eb89880e –

risposta

17

La soluzione n. 2 è l'approccio corretto, ma è necessario aggiungere una chiamata a Ecto.Migration.flush/0 dopo il primo blocco alter per assicurarsi che tutte le modifiche vengano eseguite sul database all'istante invece di essere messe in coda per essere eseguite successivamente, che è il predefinito.

def up do 
    alter table(:channels) do 
    add :type, :integer 
    end 
    flush 
    Exchat.Repo.update_all("channels", set: [type: 1]) 
    alter table(:channels) do 
    modify :type, :integer, null: false 
    end 
end