Переименование стола в рельсах

154

Я хочу переименовать таблицу ... (любую таблицу.)

Я попробовал эту строку кода:

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

Вот странная вещь. Я знаю, что это сработало в первый раз, но теперь я получаю эту ошибку: неопределенный метод `rename_table 'для ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module

Было ли что-то, что мне нужно установить?

Томми
источник

Ответы:

248

Обычно вы делаете такие вещи в процессе миграции:

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

  def self.down
    rename_table :bar, :foo
  end
end
кулачок
источник
1
Спасибо, что сработало! Я все еще озадачен, почему предыдущая строка не сделала все же. О хорошо ..
Томми
@ Томми, rename_tableметод определен в ActiveRecord::ConnectionAdapters::SchemaStatements. Он предназначен для смешивания с другими модулями. Если вы хотите запустить его напрямую, я думаю, что вы могли бы сделатьinclude ActiveRecord::ConnectionAdapters::SchemaStatements; rename_table :foo, :bar
Cam
или вы можете использовать ActiveRecord :: Migration.rename_table (: foo,: bar), если вы так склонны. Но миграция работает лучше всего. Вы также хотели бы изменить название модели или сохранить имя модели как старое? Если это так, вы можете указать имя таблицы в модели ActiveRecord, используя "set_table_name: bar".
Адитья Санги
1
Вы также можете использовать новую форму для миграции с помощью метода «change» вместо up & down. пример
MegaTux
def change, а не def self.up / def.self.down в современных реализациях Rails. Выполнение последнего потерпит молчание.
huertanix
294

Помните, что в Rails> = 3.1 вы можете использовать changeметод.

 class RenameOldTableToNewTable < ActiveRecord::Migration
   def change
     rename_table :old_table_name, :new_table_name
   end 
 end
Михаил Гришко
источник
37
Это также перенесет любые индексы с :old_table_nameна:new_table_name
Гэвин Миллер
7
Небольшой комментарий: возможно, замените на: old_named_things,: new_named_things, чтобы напомнить людям, что имена таблиц в activerecord обычно являются множественными.
Карпела
24

.rename_tableэто метод экземпляра, а не метод класса, поэтому вызов Class.methodне будет работать. Вместо этого вы должны создать экземпляр класса, и вызовите метод экземпляра, например: Class.new.method.

[РЕДАКТИРОВАТЬ] В этом случае, ActiveRecord::ConnectionAdapters::SchemaStatementsдаже не класс (как указано Cam), что означает, что вы даже не можете создать экземпляр этого в соответствии с тем, что я сказал выше. И даже если бы вы использовали пример Кэма class Foo; include ActiveRecord::ConnectionAdapters::SchemaStatements; def bar; rename_table; end; end;, это все равно не сработало бы, поскольку rename_tableвыдвигает исключение.

С другой стороны, ActiveRecord::ConnectionAdapters::MysqlAdapter это класс, и это, скорее всего , этот класс вы должны использовать , чтобы переименовать таблицу (или SQLite или PostgreSQL, в зависимости от того, что базы данных вы используете). Теперь, как это происходит, ActiveRecord::ConnectionAdapters::MysqlAdapterуже доступен через Model.connection, так что вы должны быть полностью в состоянии сделать Model.connection.rename_table, используя любую модель в вашем приложении. [/РЕДАКТИРОВАТЬ]

Однако, если вы хотите переименовать таблицу навсегда, я бы предложил использовать для этого миграцию. Это простой и предпочтительный способ управления структурой вашей базы данных с помощью Rails. Вот как это сделать:

# 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

Затем вы можете запустить миграцию с помощью rake db:migrate(которая вызывает self.upметод) и использовать rake db:rollback(которая вызывает self.down) для отмены миграции.

vonconrad
источник
Я согласен, что rename_tableэто метод экземпляра, но он не определен в классе, поэтому ваше предложение вызвать Class.new.methodне будет работать (например: ActiveRecord::ConnectionAdapters::SchemaStatements.newвыдает ошибку oMethodError: undefined method new 'для ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module`
cam
1
Также стоит отметить, что если у вас есть модель, связанная с таблицей, вы переименовываете, запускаете rake db:migrateили rake db:rollbackне будете переименовывать файл model.rb. Вам нужно будет вручную изменить файл model.rb.
9monkeys
1
В более новых версиях Rails (например, 5.x) вы можете использовать метод change вместо self.up и self.down , потому что Rails также может выполнить откат при этом. Так что только этого кода достаточно def change rename_table :my_table, :my_new_table end. , , , , Кстати: Внутри из changeвас в использовании этих команд: add_column, add_index, add_timestamps, create_table, remove_timestamps, rename_column, rename_index,rename_table
красота
2
ActiveRecord::Migration.rename_table(:old_table_name, :new_table_name)
imsinu9
источник