Zmiana nazwy stołu w szynach

154

Chcę zmienić nazwę tabeli ... (dowolnej tabeli).

Wypróbowałem ten wiersz kodu:

ActiveRecord::ConnectionAdapters::SchemaStatements.rename_table(old_name, new_name)

Oto dziwna rzecz. Wiem, że działało za pierwszym razem, ale teraz pojawia się ten błąd: niezdefiniowana metoda `rename_table 'dla ActiveRecord :: ConnectionAdapters :: SchemaStatements: Moduł

Czy było coś, co muszę ustawić?

Tommy
źródło

Odpowiedzi:

248

Podczas migracji zazwyczaj robisz takie rzeczy:

class RenameFoo < ActiveRecord::Migration
  def self.up
    rename_table :foo, :bar
  end

  def self.down
    rename_table :bar, :foo
  end
end
krzywka
źródło
1
Dzięki, że zadziałało! Nadal jestem zdziwiony, dlaczego poprzednia linia nie. No cóż…
Tommy
@Tommy, rename_tablemetoda jest zdefiniowana w pliku ActiveRecord::ConnectionAdapters::SchemaStatements. Jest przeznaczony do mieszania z innymi modułami. Jeśli chcesz uruchomić to bezpośrednio, myślę, że możesz to zrobićinclude ActiveRecord::ConnectionAdapters::SchemaStatements; rename_table :foo, :bar
kamera
lub możesz użyć ActiveRecord :: Migration.rename_table (: foo,: bar), jeśli masz takie skłonności. Ale migracja działa najlepiej. Czy chciałbyś również zmienić nazwę modelu, czy chcesz zachować nazwę modelu jako starą? Jeśli tak, możesz chcieć określić nazwę tabeli w modelu ActiveRecord za pomocą "set_table_name: bar".
Aditya Sanghi,
1
Możesz także użyć nowego formularza do migracji metodą „zmień” zamiast w górę iw dół. przykład
MegaTux
def change, a nie def self.up / def.self.down w nowoczesnych implementacjach Railsowych. Wykonanie tego ostatniego zakończy się po cichu niepowodzeniem.
huertanix
294

Pamiętaj, że w Railsach> = 3.1 możesz użyć tej changemetody.

 class RenameOldTableToNewTable < ActiveRecord::Migration
   def change
     rename_table :old_table_name, :new_table_name
   end 
 end
Michaił Grishko
źródło
37
Spowoduje to również migrację wszystkich indeksów z :old_table_namedo:new_table_name
Gavin Miller
7
Mały komentarz: Być może zmień na: old_named_things,: new_named_things, aby przypomnieć ludziom, że nazwy tabel w activerecord są generalnie w liczbie mnogiej.
Carpela,
24

.rename_tablejest metodą instancji, a nie metodą klasową, więc wywołanie Class.methodnie będzie działać. Zamiast tego musisz utworzyć instancję klasy i wywołać metodę na przykład tak: Class.new.method.

[EDYTUJ] W tym przypadku ActiveRecord::ConnectionAdapters::SchemaStatementsnie jest to nawet klasa (na co wskazuje cam), co oznacza, że ​​nie można nawet utworzyć jej instancji zgodnie z tym, co powiedziałem powyżej. Nawet jeśli użyjesz przykładu z kamery class Foo; include ActiveRecord::ConnectionAdapters::SchemaStatements; def bar; rename_table; end; end;, to nadal nie zadziała, ponieważ rename_tablewywołuje wyjątek.

Z drugiej strony ActiveRecord::ConnectionAdapters::MysqlAdapter jest to klasa i prawdopodobnie ta klasa musiałabyś użyć do zmiany nazwy tabeli (lub SQLite lub PostgreSQL, w zależności od używanej bazy danych). Teraz, jak to się dzieje, ActiveRecord::ConnectionAdapters::MysqlAdapterjest już dostępne przez Model.connection, więc powinieneś być w stanie to zrobić Model.connection.rename_table, używając dowolnego modelu w swojej aplikacji. [/EDYTOWAĆ]

Jeśli jednak chcesz trwale zmienić nazwę tabeli, sugerowałbym skorzystanie z migracji, aby to zrobić. Jest to łatwy i preferowany sposób manipulowania strukturą bazy danych w Railsach. Oto jak to zrobić:

# Commandline
rails generate migration rename_my_table

# In db/migrate/[timestamp]_rename_my_table.rb:
class RenameMyTable < ActiveRecord::Migration
  def self.up
    rename_table :my_table, :my_new_table
  end

  def self.down
    rename_table :my_new_table, :my_table
  end
end

Następnie możesz uruchomić migrację za pomocą rake db:migrate(która wywołuje self.upmetodę) i użyć rake db:rollback(które wywołania self.down), aby cofnąć migrację.

vonconrad
źródło
Zgadzam się, że rename_tablejest to metoda instancji, ale nie jest zdefiniowana w klasie, więc Twoja sugestia wywołania Class.new.methodnie zadziała (na przykład: ActiveRecord::ConnectionAdapters::SchemaStatements.newwyświetla oMethodError: undefined method nowy błąd 'for ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module`
cam
1
Warto również zauważyć, że jeśli masz model powiązany z tabelą, zmieniasz nazwę, uruchamiasz rake db:migratelub rake db:rollbacknie zmienisz nazwy pliku model.rb. Będziesz musiał ręcznie zmienić plik model.rb.
małp
1
W nowszych wersjach Railsów (np. 5.x) możesz użyć metody change zamiast self.up i self.down , ponieważ Railsy mogą również przez to wykonać wycofanie. Więc po prostu ten kod jest na tyle: def change rename_table :my_table, :my_new_table end. . . . . Przy okazji: wewnątrz changewam używać tych poleceń: add_column, add_index, add_timestamps, create_table, remove_timestamps, rename_column, rename_index,rename_table
Uroda
2
ActiveRecord::Migration.rename_table(:old_table_name, :new_table_name)
imsinu9
źródło