Add rake task for fixing invalid canvas positions

This commit is contained in:
Urban Rotnik 2019-09-26 08:47:43 +02:00
parent 43e3763ec8
commit d5716c4260
2 changed files with 80 additions and 0 deletions

40
lib/tasks/my_modules.rake Normal file
View file

@ -0,0 +1,40 @@
# frozen_string_literal: true
# On production around 2k records for repair, for production DB it tooked cca 1 min
# rubocop:disable Metrics/BlockLength
namespace :my_modules do
desc 'Find new positions on canvas for already taken coordiantes'
task fix_positions: :environment do
query = MyModule.select('COUNT(*) as duplicates', :x, :y, :experiment_id)
.where(archived: false)
.group(:x, :y, :experiment_id)
.having('COUNT(*)>1')
Rails.logger.info '*********************************************************************************'
Rails.logger.info "You have to relocate #{query.sum { |a| a.duplicates - 1 }} tasks"
Rails.logger.info '*********************************************************************************'
query.each do |row|
tasks_to_update = MyModule.where(experiment_id: row.experiment, x: row.x, y: row.y, archived: false)
.order(created_at: :asc)
.offset(1)
tasks_to_update.find_each do |task|
coordinates = task.get_new_position
task.attributes = coordinates
begin
task.save!
Rails.logger.info "Relocated task with ID #{task.id}"
rescue ActiveRecord::RecordInvalid => e
Rails.logger.error "Unable to save task with ID #{task.id}: #{e.message}"
end
end
end
Rails.logger.info '*********************************************************************************'
Rails.logger.info "You have #{query.reload.sum { |a| a.duplicates - 1 }} tasks on invalid positions"
Rails.logger.info '*********************************************************************************'
end
end
# rubocop:enable Metrics/BlockLength

View file

@ -0,0 +1,40 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'my_modules:fix_positions' do
include_context 'rake'
before(:all) do
experiment = create :experiment
100.times do
create :my_module, experiment: experiment
end
# set 30 tasks same position
my_modules_with_same_position = MyModule.limit(10)
my_modules_with_same_position.update_all(x: 0, y: 0)
# 1 module should be invalid
my_modules_with_same_position.second.update_column(:name, 'a')
my_modules_with_same_position.third.update_column(:archived, true)
end
context 'when record is valid except position' do
it 'changes position for my_module' do
expect { subject.invoke }.to(change { MyModule.find(5).y })
end
end
context 'when record is invalid' do
it 'remains error on position' do
subject.invoke
my_module = MyModule.find_by(name: 'a')
my_module.valid?
expect(my_module.errors.messages[:position])
.to(eq ['and Y position has already been taken by another task in the experiment.'])
end
end
end