Merge pull request #2986 from consul/backport-migrate_globalize_data
Migrate globalize data
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@ class AddPollQuestionTranslations < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
Poll::Question.create_translation_table!(
|
||||
title: :string
|
||||
{ title: :string },
|
||||
{ migrate_data: true }
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
89
lib/tasks/globalize.rake
Normal 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
|
||||
168
spec/lib/tasks/globalize_spec.rb
Normal file
168
spec/lib/tasks/globalize_spec.rb
Normal 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
|
||||
Reference in New Issue
Block a user