Merge pull request #2986 from consul/backport-migrate_globalize_data

Migrate globalize data
This commit is contained in:
Javier Martín
2018-10-26 12:23:53 +02:00
committed by GitHub
12 changed files with 326 additions and 35 deletions

View File

@@ -1,9 +1,12 @@
class AddTranslateMilestones < ActiveRecord::Migration
def self.up
Budget::Investment::Milestone.create_translation_table!({
title: :string,
description: :text
})
Budget::Investment::Milestone.create_translation_table!(
{
title: :string,
description: :text
},
{ migrate_data: true }
)
end
def self.down

View File

@@ -6,7 +6,10 @@ class CreateI18nContentTranslations < ActiveRecord::Migration
reversible do |dir|
dir.up do
I18nContent.create_translation_table! :value => :text
I18nContent.create_translation_table!(
{ value: :text },
{ migrate_data: true }
)
end
dir.down do

View File

@@ -2,8 +2,11 @@ class AddBannerTranslations < ActiveRecord::Migration
def self.up
Banner.create_translation_table!(
title: :string,
description: :text
{
title: :string,
description: :text
},
{ migrate_data: true }
)
end

View File

@@ -2,10 +2,13 @@ class AddHomepageContentTranslations < ActiveRecord::Migration
def self.up
Widget::Card.create_translation_table!(
label: :string,
title: :string,
description: :text,
link_text: :string
{
label: :string,
title: :string,
description: :text,
link_text: :string
},
{ migrate_data: true }
)
end

View File

@@ -2,9 +2,12 @@ class AddPollTranslations < ActiveRecord::Migration
def self.up
Poll.create_translation_table!(
name: :string,
summary: :text,
description: :text
{
name: :string,
summary: :text,
description: :text
},
{ migrate_data: true }
)
end

View File

@@ -2,8 +2,11 @@ class AddAdminNotificationTranslations < ActiveRecord::Migration
def self.up
AdminNotification.create_translation_table!(
title: :string,
body: :text
{
title: :string,
body: :text
},
{ migrate_data: true }
)
end

View File

@@ -2,7 +2,8 @@ class AddPollQuestionTranslations < ActiveRecord::Migration
def self.up
Poll::Question.create_translation_table!(
title: :string
{ title: :string },
{ migrate_data: true }
)
end

View File

@@ -2,8 +2,11 @@ class AddPollQuestionAnswerTranslations < ActiveRecord::Migration
def self.up
Poll::Question::Answer.create_translation_table!(
title: :string,
description: :text
{
title: :string,
description: :text
},
{ migrate_data: true }
)
end

View File

@@ -2,25 +2,33 @@ class AddCollaborativeLegislationTranslations < ActiveRecord::Migration
def self.up
Legislation::Process.create_translation_table!(
title: :string,
summary: :text,
description: :text,
additional_info: :text,
{
title: :string,
summary: :text,
description: :text,
additional_info: :text,
},
{ migrate_data: true }
)
Legislation::Question.create_translation_table!(
title: :text
{ title: :text },
{ migrate_data: true }
)
Legislation::DraftVersion.create_translation_table!(
title: :string,
changelog: :text,
body: :text,
body_html: :text,
toc_html: :text
{
title: :string,
changelog: :text,
body: :text,
body_html: :text,
toc_html: :text
},
{ migrate_data: true }
)
Legislation::QuestionOption.create_translation_table!(
value: :string
{ value: :string },
{ migrate_data: true }
)
end

View File

@@ -1,10 +1,14 @@
class AddTranslatePages < ActiveRecord::Migration
def self.up
SiteCustomization::Page.create_translation_table!({
title: :string,
subtitle: :string,
content: :text
})
SiteCustomization::Page.create_translation_table!(
{
title: :string,
subtitle: :string,
content: :text
},
{ migrate_data: true }
)
change_column :site_customization_pages, :title, :string, :null => true
end

89
lib/tasks/globalize.rake Normal file
View File

@@ -0,0 +1,89 @@
namespace :globalize do
def translatable_classes
[
AdminNotification,
Banner,
Budget::Investment::Milestone,
I18nContent,
Legislation::DraftVersion,
Legislation::Process,
Legislation::Question,
Legislation::QuestionOption,
Poll,
Poll::Question,
Poll::Question::Answer,
SiteCustomization::Page,
Widget::Card
]
end
def migrate_data
@errored = false
translatable_classes.each do |model_class|
logger.info "Migrating #{model_class} data"
fields = model_class.translated_attribute_names
model_class.find_each do |record|
fields.each do |field|
locale = if model_class == SiteCustomization::Page && record.locale.present?
record.locale
else
I18n.locale
end
translated_field = record.localized_attr_name_for(field, locale)
if record.send(translated_field).blank?
record.send(:"#{translated_field}=", record.untranslated_attributes[field.to_s])
end
end
begin
record.save!
rescue ActiveRecord::RecordInvalid
logger.warn "Failed to save #{model_class} with id #{record.id}"
@errored = true
end
end
end
end
def logger
@logger ||= Logger.new(STDOUT).tap do |logger|
logger.formatter = proc { |severity, _datetime, _progname, msg| "#{severity} #{msg}\n" }
end
end
def errored?
@errored
end
desc "Simulates migrating existing data to translation tables"
task simulate_migrate_data: :environment do
logger.info "Starting migrate data simulation"
ActiveRecord::Base.transaction do
migrate_data
raise ActiveRecord::Rollback
end
if errored?
logger.warn "Some database records will not be migrated"
else
logger.info "Migrate data simulation ended successfully"
end
end
desc "Migrates existing data to translation tables"
task migrate_data: :environment do
logger.info "Starting data migration"
migrate_data
logger.info "Finished data migration"
if errored?
logger.warn "Some database records couldn't be migrated; please check the log messages"
end
end
end

View File

@@ -0,0 +1,168 @@
require "rails_helper"
require "rake"
describe "Globalize tasks" do
describe "#migrate_data" do
before do
Rake.application.rake_require "tasks/globalize"
Rake::Task.define_task(:environment)
end
let :run_rake_task do
Rake::Task["globalize:migrate_data"].reenable
Rake.application.invoke_task "globalize:migrate_data"
end
context "Original data with no translated data" do
let(:poll) do
create(:poll).tap do |poll|
poll.translations.delete_all
poll.update_column(:name, "Original")
poll.reload
end
end
it "copies the original data" do
expect(poll.send(:"name_#{I18n.locale}")).to be nil
expect(poll.name).to eq("Original")
run_rake_task
poll.reload
expect(poll.name).to eq("Original")
expect(poll.send(:"name_#{I18n.locale}")).to eq("Original")
end
end
context "Original data with blank translated data" do
let(:banner) do
create(:banner).tap do |banner|
banner.update_column(:title, "Original")
banner.translations.first.update_column(:title, "")
end
end
it "copies the original data" do
expect(banner.title).to eq("")
run_rake_task
banner.reload
expect(banner.title).to eq("Original")
expect(banner.send(:"title_#{I18n.locale}")).to eq("Original")
end
end
context "Original data with translated data" do
let(:notification) do
create(:admin_notification, title: "Translated").tap do |notification|
notification.update_column(:title, "Original")
end
end
it "maintains the translated data" do
expect(notification.title).to eq("Translated")
run_rake_task
notification.reload
expect(notification.title).to eq("Translated")
expect(notification.send(:"title_#{I18n.locale}")).to eq("Translated")
end
end
context "Custom page with a different locale and no translations" do
let(:page) do
create(:site_customization_page, locale: :fr).tap do |page|
page.translations.delete_all
page.update_column(:title, "en Français")
page.reload
end
end
it "copies the original data to both the page's locale" do
expect(page.title).to eq("en Français")
expect(page.title_fr).to be nil
expect(page.send(:"title_#{I18n.locale}")).to be nil
run_rake_task
page.reload
expect(page.title).to eq("en Français")
expect(page.title_fr).to eq("en Français")
expect(page.send(:"title_#{I18n.locale}")).to be nil
end
end
context "Custom page with a different locale and existing translations" do
let(:page) do
create(:site_customization_page, title: "In English", locale: :fr).tap do |page|
page.update_column(:title, "en Français")
end
end
it "copies the original data to the page's locale" do
expect(page.title_fr).to be nil
expect(page.title).to eq("In English")
run_rake_task
page.reload
expect(page.title).to eq("In English")
expect(page.title_fr).to eq("en Français")
expect(page.send(:"title_#{I18n.locale}")).to eq("In English")
end
end
context "Invalid data" do
let!(:valid_process) do
create(:legislation_process).tap do |process|
process.translations.delete_all
process.update_column(:title, "Title")
process.reload
end
end
let!(:invalid_process) do
create(:legislation_process).tap do |process|
process.translations.delete_all
process.update_column(:title, "")
process.reload
end
end
it "ignores invalid data and migrates valid data" do
expect(valid_process).to be_valid
expect(invalid_process).not_to be_valid
run_rake_task
expect(valid_process.translations.count).to eq 1
expect(valid_process.reload.title).to eq "Title"
expect(invalid_process.translations.count).to eq 0
expect(invalid_process.reload.title).to eq ""
end
end
context "locale with non-underscored name" do
before { I18n.locale = :"pt-BR" }
let!(:milestone) do
create(:budget_investment_milestone).tap do |milestone|
milestone.translations.delete_all
milestone.update_column(:title, "Português")
milestone.reload
end
end
it "runs the migration successfully" do
run_rake_task
expect(milestone.reload.title).to eq "Português"
end
end
end
end