
TL; DR Mova seu código de migração de dados para tarefas Rake ou use joias completas de estilo de esquema. Cubra essa lógica com testes.
Estou trabalhando como desenvolvedor de back-end na FunBox. Em vários projetos, estamos escrevendo um back-end Ruby On Rails. Procuramos construir processos de desenvolvimento adequados, portanto, diante de um problema, procuramos compreendê-lo e desenvolver recomendações metodológicas. Isso também aconteceu com o problema da migração de dados. Certa vez, fiz a migração de dados em uma tarefa Rake separada coberta com testes, e a equipe tinha uma pergunta: "Por que não na migração de esquema?" Perguntei aos desenvolvedores no chat interno e, para minha surpresa, as opiniões se dividiram. Ficou claro que a pergunta era ambígua e digna de uma análise cuidadosa e de um artigo. O programa máximo em termos de objetivos para um artigo será cumprido para mim quando alguém citar um link para este texto na revisão do código em resposta à pergunta por que uma determinada migração de dados foi retirada ou, ao contrário, não retirada da migração de esquema.
Digressão lírica
IT . Ruby, - . , , . , : , , , , , , .
, , . , , , , .
— , (views), , . .
— (, , , .) . . , . CI, , ( ) SQL , .
— . , DML- UPDATE SQL. . .
(Continuous Delivery) — , .
Rails , , DDL-. , . , Rails omakase- . , .
, , . , . , , . .
. , . (, ) , .
, . . -, , .
deadlocks .
, , , Zero Downtime Migrations Strong Migrations.
— DSL (Domain Specific Language) Ruby DDL- SQL . DSL, , . , .
DSL, , SRP. . , , …
( , )
Ruby On Rails Data Migration , . , . Rails-, . .
SQL ORM ActiveRecord.
:
- . .
- , .
- callbacks , .
«» . , .
# db/migrate/20100513121110_add_flag_to_product.rb
class AddFlagToProduct < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
def change
add_column :products, :flag, :boolean
Product.reset_column_information
Product.all.each do |product|
product.update_attributes!(:flag => false)
end
end
end
.
, each find_each c batch-.
SQL
, , SQL, :
- , . , , , (SQL), .
- JOIN-, , .
- , deadlock.
,
, .
, nullable- .
, .
, :
UPDATE table SET field = 'f' WHERE field IS NULL
:
class ClientDemandsMakeApprovedNullable < ActiveRecord::Migration
def up
change_column_null :client_demands, :approved, true
change_column_default :client_demands, :approved, nil
end
def down
execute("UPDATE client_demands SET approved = 'f' WHERE approved IS NULL")
change_column_null :client_demands, :approved, false
change_column_default :client_demands, :approved, false
end
end
, . , , . Dan Mayer Managing DB Schema & Data Changes Modifying Large Tables.
. «», . . , , , .
, .
, , .
, . . REPL .
, :
- ;
- ;
- .
. , . . .
, , , , .
Rake-
, — Rake-. . -.
Rake- . , . . . — .
, , Rake, Thoughtbot:
# lib/tasks/temporary/users.rake
namespace :users do
desc "Actualize achievements counter cache"
task actualize_achievements_counter_cache: :environment do
# C (ActiveRelation)
users = User.with_achievements
#
puts "Going to update #{users.count} users"
# , ,
# .
ActiveRecord::Base.transaction do
# Batch- find_each
users.find_each do |user|
#
user.actualize_achievements_counter_cache!
#
print "."
end
end
puts "Done!"
end
end
each find_each, . memory bloats. Akshay Mohite.
. , Rake- .
, . . , , . .
Mark Qualie up, . «» . :
class AddLastSmiledAtColumnToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :last_smiled_at, :datetime
add_index :users, :last_smiled_at
end
class Data
def up
User.all.find_in_batches(batch_size: 250).each do |group|
ActiveRecord::Base.transaction do
group.each do |user|
user.last_smiled_at = user.smiles.last.created_at
user.save if user.changed?
end
end
end
end
end
end
:
Dir.glob("#{Rails.root}/db/migrate/*.rb").each { |file| require file }
AddLastSmiledAtColumnToUsers::Data.new.up
Job, .
, - , .
, , .
, . , .
data-migrate (> 670), , Readme. Rails 5+.
, Rails 4+:
rails-data-migrations(> 93 )
nonschema_migrations(> 53 )
. .
, Rake-. . , .
db/data, db/migrate c :
rails g data_migration add_this_to_that
:
rake data:migrate
rake db:migrate:with_data
rake db:rollback:with_data
rake db:migrate:status:with_data
, .
| Rails | Rake | ||||
|---|---|---|---|---|---|
| + | - | - | - | - | |
| Zero Downtime Deployment | - | + | + | + | + |
| Test First | - | - | + | + | |
| + | - | - | + | ||
| + | - | + | + | + | |
| + | - | - | + | + |
.
— , :
- — ;
- Zero Downtime Deployment — , ;
- Test First — ;
- — ;
- — , ;
- — , , .
, Rake- — .
, . .
, — , . , .
- Rails Guides.
- Thoughtbot. Data Migrations in Rails.
- AtomicObject. Testing Data Migrations in Rails.
- Marcqualie. Rails Data Migrations.
- Ombulabs. Three Useful Data Migration Patterns for Rails.
- Strong Migrations.
- Zero Downtime Migrations.
- Dan Mayer. Managing DB Schema & Data Change.
Akshay Mohite find_eacheach.- . « . ». 1, 8 . , , .
UPD 2020-08-06: Extrapolator « ».
- , Test First .
.
UPD 2020-08-07: . , . . , .