81

Podczas pierwszej migracji zadeklarowałem w kolumnie content, że będzie ciągiem Activerecord utworzył ciąg znaków (255) zgodnie z klejnotem adnotacji.Zmiana typu kolumny na dłuższe łańcuchy w szynach

Po wciskam aplikację do Heroku, która wykorzystuje postgres, jeśli wejdę w postaci zawartości ciąg dłużej niż 255 pojawia się błąd

PGError: ERROR: value too long for type character varying(255) 

Problem polega na tym, że trzeba, że ​​treść zawierać ciąg to może być bardzo długa (dowolny tekst, może być tysiące znaków)

  1. Jaką zmienną (czy łańcuch nie jest odpowiedni do tego) może pg przyjąć?
  2. Jak mogę utworzyć migracji zastąpić typ tej kolumnie

dzięki

Odpowiedz

193

należy użyć text z szynami jeśli chcesz ciąg bez limitu długości. Migracja taka jak ta:

def up 
    change_column :your_table, :your_column, :text 
end 
def down 
    # This might cause trouble if you have strings longer 
    # than 255 characters. 
    change_column :your_table, :your_column, :string 
end 

powinna rozwiązać problemy. Możesz potrzebować :null => false lub innych opcji na końcu tego też.

Gdy używasz kolumny string bez określonego limitu, Railsy dodają domyślny :limit => 255. Ale jeśli użyjesz text, otrzymasz dowolny ciąg znaków o dowolnej długości, jaki obsługuje baza danych. PostgreSQL umożliwia korzystanie z kolumny varchar bez żadnej długości, ale większość baz danych używa oddzielnego typu, a Rails nie zna numeru varchar bez żadnej długości. Musisz użyć text w Railsach, aby uzyskać text column w PostgreSQL. Nie ma różnicy w PostgreSQL między kolumną typu text i jedną z typów varchar (ale inna jest). Co więcej, jeśli wdrażasz system PostgreSQL, nie ma powodu, aby w ogóle używać :string (AKA varchar), baza danych traktuje je jako wewnętrzne, z wyjątkiem dodatkowych ograniczeń długości dla varchar(n); powinieneś używać tylko varchar(n) (AKA :string), jeśli masz zewnętrzne ograniczenie (takie jak formularz rządowy, który mówi, że pole 432 w formularzu 897/B ma długość 23 znaków) w rozmiarze kolumny.

Tak na marginesie, jeśli używasz kolumnę string wszędzie, zawsze należy podać :limit jako przypomnienie sobie, że istnieje granica, a trzeba mieć sprawdzania poprawności w modelu, aby zapewnić, że limit nie został przekroczony . Jeśli przekroczysz limit, PostgreSQL złoży skargę i zgłosi wyjątek, MySQL cicho skróci ciąg lub złoży skargę (w zależności od konfiguracji serwera), SQLite pozwoli mu przejść tak jak jest, a inne bazy danych zrobią coś innego (prawdopodobnie narzekają) .

Powinieneś także rozwijać, testować i wdrażać na tej samej bazie danych (która zazwyczaj będzie PostgreSQL w Heroku), powinieneś nawet używać tych samych wersji serwera bazy danych. Istnieją inne różnice między bazami danych (np. Zachowanie GROUP BY), których ActiveRecord nie będzie was izolować. Być może już to robisz, ale pomyślałem, że i tak o tym wspomnę.

+13

Wielką odpowiedź. Jedna uwaga: Railsy obecnie nie obsługują kolumna zmiany z metodą zmiany (http://guides.rubyonrails.org/migrations.html#using-the-change-method); jeśli pamięć się wyświetli, utworzysz nieodwracalną migrację, jeśli to zrobisz. Lepiej to zrobić w starym stylu metodami "góra/dół". – poetmountain

+0

@BourbonJockey: To ma sens, że 'zmiana' nie będzie w stanie automatycznie odwrócić zmiany typu, a [Przewodnik migracji] (http://guides.rubyonrails.org/migrations.html#anomomy-ofa-a- migracja) mówi, że "[metoda zmiany] Ta metoda jest preferowana do pisania konstruktywnych migracji (dodawania kolumn lub tabel)" i "zmienna_kolumna" nie znajduje się na liście, którą wskażesz, więc myślę, że masz rację. Naprawiłem to, aby użyć 'up' /' down' (z zastrzeżeniem na 'down'), dzięki za heads up. –

+4

Dla przyszłych referencji czytelników, konwersja z ciągu znaków na tekst w Postgres na Heroku w ten sposób NIE spowoduje utraty danych. –

0

Chociaż przyjęta odpowiedź jest doskonała, chciałem dodać tutaj odpowiedź, że mam nadzieję, że lepsze oferty z oryginalnymi plakatami będą kwestionować część 2, dla nie takich ekspertów jak ja.

  1. How do I create a migration to replace the type of that column

generowania migracji oraz rusztowanie

Można wygenerować migrację trzymać zmiany wpisując w konsoli (wystarczy wymienić table dla nazwy tabel, a column dla ciebie kolumna nazwa)

rails generate migrate change_table_column 

Spowoduje to migrację szkieletu wewnątrz ciebie Rails application/db/migrate/folder. Ta migracja jest symbolem zastępczym dla Twojego kodu migracji.

Na przykład chcę utworzyć migracji, aby zmienić typ kolumny z string do text, w tabeli zatytułowanej TodoItems:

class ChangeTodoItemsDescription < ActiveRecord::Migration 
    def change 
    # enter code here 
    change_column :todo_items, :description, :text 
    end 
end 

przeprowadzania migracji

Gdy masz wprowadzono kod, aby zmienić kolumnę po prostu uruchomić:

rake db:migrate 

Aby zastosować migrati na. Jeśli popełnisz błąd, zawsze można cofnąć zmiany z:

rake db:rollack 

górę iw dół metod

Przyjęte referencje odpowiedź Up i Down metody, zamiast nowszej Change metody. Ponieważ rails 3.2stary styl Metody Up and Down prezentowały kilka zalet w stosunku do nowszej metody Change. "W górę i w dół" unikaj ActiveRecord::IrreversibleMigration exception. Od czasu wydania Rails 4 można użyć reversible aby uniknąć tego błędu:

class ChangeProductsPrice < ActiveRecord::Migration 
    def change 
    reversible do |dir| 
     change_table :products do |t| 
     dir.up { t.change :price, :string } 
     dir.down { t.change :price, :integer } 
     end 
    end 
    end 
end 

Ciesz Rails :)

Powiązane problemy