ruby-on-rails - remove - rollback migration rails
¿Cómo muevo una columna(con contenido) a otra tabla en una migración de Rails? (7)
Esto es lo que hice en mi proyecto:
class MoveColumnDataToUsersTable < ActiveRecord::Migration[5.1]
def up
add_column :users, :someprop, :string
User.find_each do |u|
Profile.create!(user_id: u.id, someprop: someprop)
end
remove_column :profiles, :someprop
end
def down
add_column :profiles, :someprop, :someprop_data_type
Profile.find_each do |p|
User.find_by(id: p.user_id).update_columns(someprop: p.someprop)
end
Profile.destroy_all
end
end
Necesito mover algunas columnas de una tabla existente a otra. ¿Cómo lo hago utilizando una migración de rieles?
class AddPropertyToUser < ActiveRecord::Migration
def self.up
add_column :users, :someprop, :string
remove_column :profiles, :someprop
end
def self.down
add_column :profiles, :someprop, :string
remove_column :users, :someprop
end
end
Lo anterior solo crea las nuevas columnas, pero los valores se dejan vacíos ...
Quiero evitar iniciar sesión en la base de datos para actualizar manualmente las tablas.
Si hay una forma de mover los valores de columna mediante programación, ¿cuáles son las características de rendimiento? ¿Lo haría fila por fila, o hay una manera de actualizar en masa?
Haría esto como tres migraciones, o una migración de tres partes. La primera parte es agregar la columna, la segunda parte es copiar los datos y la tercera parte es soltar la columna.
Parece que el paso medio es lo que estás preguntando, puedes hacer esto en ruby haciendo un bucle entre todos los usuarios y configurando la propiedad, de esta manera:
Users.each do |user|
user.someprop = user.profile.some_prop
user.save
end
No amo esta forma de hacerlo, porque es muy lenta. Yo sugeriría la ejecución de sql sin formato como este:
execute "UPDATE users u, profiles p SET u.someprop=p.someprop WHERE u.id=p.user_id"
Ambos asumen algo acerca de su perfil / asociación de usuarios, que puede ajustar si yo asumí mal.
La siguiente sintaxis de UPDATE
funciona para las versiones recientes de Postgres y evita una subconsulta:
class MoveSomePropertyToUser < ActiveRecord::Migration
def self.up
add_column :users, :some_property, :string
execute "UPDATE users u SET some_property = p.some_property FROM profiles p WHERE u.id = p.user_id;"
remove_column :profiles, :some_property
end
def self.down
add_column :profiles, :some_property, :string
execute "UPDATE profiles p SET some_property = u.some_property FROM users u WHERE p.user_id = u.id;"
remove_column :users, :some_property
end
end
La sintaxis no funciona para versiones posteriores de Postgres. Para obtener una respuesta actualizada de @ Eero''s for Postges 9.4.5, haga lo siguiente:
class AddPropertyToUser < ActiveRecord::Migration
def self.up
add_column :users, :someprop, :string
execute "UPDATE users u SET someprop = (SELECT p.someprop FROM profiles p WHERE u.id = p.user_id);"
remove_column :profiles, :someprop
end
def self.down
add_column :profiles, :someprop, :string
execute "UPDATE profiles p SET someprop = (SELECT u.someprop FROM users u WHERE p.user_id = u.id);"
remove_column :users, :someprop
end
end
Para mí (postgreSQL 9.1) el RAW SQL no funcionó. Lo he cambiado:
" UPDATE users u
SET someprop = (SELECT p.someprop
FROM profiles p
WHERE u.id = p.user_id );"
Puede evitar las sentencias de SQL específicas de la base de datos codificadas por update_all con update_all y / o find_each
Terminé usando esta migración (probado, funciona y se deshace con éxito):
class AddPropertyToUser < ActiveRecord::Migration
def self.up
add_column :users, :someprop, :string
execute "UPDATE users u, profiles p SET u.someprop = p.someprop WHERE u.id = p.user_id"
remove_column :profiles, :someprop
end
def self.down
add_column :profiles, :someprop, :string
execute "UPDATE profiles p, users u SET p.someprop = u.someprop WHERE p.user_id = u.id"
remove_column :users, :someprop
end
end
Me gusta porque evita las actualizaciones fila por fila en una gran base de datos.