Add method to retrieve translations in one database query
This methods performs much better when we need to load a lot of globalized models translations and returns the best fallback translation for the current language.
This commit is contained in:
@@ -100,5 +100,22 @@ module Globalizable
|
|||||||
def translation_class_delegate(method)
|
def translation_class_delegate(method)
|
||||||
translation_class.instance_eval { delegate method, to: :globalized_model }
|
translation_class.instance_eval { delegate method, to: :globalized_model }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_fallback_translation
|
||||||
|
translations_foreign_key = reflect_on_association(:translations).foreign_key
|
||||||
|
fallbacks = Globalize.fallbacks(Globalize.locale)
|
||||||
|
|
||||||
|
fallbacks_with_order = fallbacks.map.with_index do |locale, order|
|
||||||
|
"('#{locale}', #{order})"
|
||||||
|
end.join(", ")
|
||||||
|
|
||||||
|
translations_ids = translation_class
|
||||||
|
.select("DISTINCT ON (#{translations_foreign_key}) id")
|
||||||
|
.where(locale: fallbacks)
|
||||||
|
.joins("LEFT JOIN (VALUES #{fallbacks_with_order}) AS locales(name, ordering) ON locale = locales.name")
|
||||||
|
.order(translations_foreign_key, "locales.ordering")
|
||||||
|
|
||||||
|
with_translations(fallbacks).where("#{translations_table_name}.id": translations_ids)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,10 +15,7 @@ shared_examples_for "globalizable" do |factory_name|
|
|||||||
before do
|
before do
|
||||||
record.update!(attribute => "In English")
|
record.update!(attribute => "In English")
|
||||||
|
|
||||||
I18n.with_locale(:es) do
|
add_translation(record, :es, "En español")
|
||||||
record.update!(required_fields.index_with("En español"))
|
|
||||||
record.update!(attribute => "En español")
|
|
||||||
end
|
|
||||||
|
|
||||||
record.reload
|
record.reload
|
||||||
end
|
end
|
||||||
@@ -98,7 +95,7 @@ shared_examples_for "globalizable" do |factory_name|
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "Does not automatically add a translation for the current locale" do
|
it "Does not automatically add a translation for the current locale" do
|
||||||
record.translations.find_by(locale: :en).destroy!
|
destroy_translation(record, :en)
|
||||||
record.reload
|
record.reload
|
||||||
|
|
||||||
record.update!(translations_attributes: [
|
record.update!(translations_attributes: [
|
||||||
@@ -188,4 +185,62 @@ shared_examples_for "globalizable" do |factory_name|
|
|||||||
expect(record.send(attribute)).to eq "Deutsche Sprache"
|
expect(record.send(attribute)).to eq "Deutsche Sprache"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe ".with_fallback_translation" do
|
||||||
|
before do
|
||||||
|
fallbacks = { fr: %i[fr en es], es: %i[es fr en], en: %i[en es fr] }
|
||||||
|
allow(I18n).to receive(:fallbacks).and_return(I18n.fallbacks.merge(fallbacks))
|
||||||
|
Globalize.set_fallbacks_to_all_available_locales
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns records with the best fallback translation available for the current locale" do
|
||||||
|
record.update!(attribute => "Content in English")
|
||||||
|
add_translation(record, :es, "Contenido en español")
|
||||||
|
add_translation(record, :fr, "Contenu en français")
|
||||||
|
|
||||||
|
I18n.with_locale(:es) do
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Contenido en español"
|
||||||
|
|
||||||
|
destroy_translation(record, :es)
|
||||||
|
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Contenu en français"
|
||||||
|
|
||||||
|
destroy_translation(record, :fr)
|
||||||
|
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Content in English"
|
||||||
|
end
|
||||||
|
|
||||||
|
record.reload
|
||||||
|
|
||||||
|
add_translation(record, :es, "Contenido en español")
|
||||||
|
add_translation(record, :fr, "Contenu en français")
|
||||||
|
|
||||||
|
I18n.with_locale(:fr) do
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Contenu en français"
|
||||||
|
|
||||||
|
destroy_translation(record, :fr)
|
||||||
|
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Content in English"
|
||||||
|
|
||||||
|
destroy_translation(record, :en)
|
||||||
|
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Contenido en español"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_translation(record, locale, text)
|
||||||
|
I18n.with_locale(locale) do
|
||||||
|
record.update!(required_fields.index_with(text))
|
||||||
|
record.update!(attribute => text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_translation(record, locale)
|
||||||
|
record.translations.find_by(locale: locale).destroy!
|
||||||
|
end
|
||||||
|
|
||||||
|
def attribute_with_fallback_translation(record, attribute)
|
||||||
|
record.class.with_fallback_translation.where(id: record.id).pick(attribute)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user