From 41dba842a6de94235b777c6703ef218443a37fc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Fri, 20 Nov 2020 00:35:24 +0100 Subject: [PATCH] Cache I18nContent translations This way we avoid fetching each translation every time it's requested. This reduces the amount of queries in the development logs and also makes the test suite faster. --- app/models/i18n_content.rb | 8 ++++++ config/initializers/i18n_translation.rb | 4 +-- spec/models/i18n_content_spec.rb | 37 +++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/app/models/i18n_content.rb b/app/models/i18n_content.rb index 53af6f51e..1bcaea82b 100644 --- a/app/models/i18n_content.rb +++ b/app/models/i18n_content.rb @@ -94,4 +94,12 @@ class I18nContent < ApplicationRecord budgets.index.section_footer.description ] end + + def self.translations_hash(locale) + Rails.cache.fetch(translation_class.where(locale: locale)) do + all.map do |content| + [content.key, translation_class.find_by(i18n_content_id: content, locale: locale)&.value] + end.to_h + end + end end diff --git a/config/initializers/i18n_translation.rb b/config/initializers/i18n_translation.rb index 1b567065f..e681570a7 100644 --- a/config/initializers/i18n_translation.rb +++ b/config/initializers/i18n_translation.rb @@ -8,10 +8,8 @@ module ActionView def t(key, options = {}) current_locale = options[:locale].presence || I18n.locale + translation = I18nContent.translations_hash(current_locale)[key] - i18_content = I18nContent.find_by(key: key) - translation = I18nContentTranslation.find_by(i18n_content_id: i18_content&.id, - locale: current_locale)&.value if translation.present? translation % options else diff --git a/spec/models/i18n_content_spec.rb b/spec/models/i18n_content_spec.rb index 6bda3e458..1a238cc61 100644 --- a/spec/models/i18n_content_spec.rb +++ b/spec/models/i18n_content_spec.rb @@ -118,4 +118,41 @@ RSpec.describe I18nContent, type: :model do }) end end + + describe ".translations_hash" do + let!(:content) { create(:i18n_content, key: "great", value_en: "Custom great", value_es: nil) } + + it "gets the translations" do + expect(I18nContent.translations_hash(:en)["great"]).to eq "Custom great" + end + + it "does not use fallbacks, so YAML files will be used instead" do + expect(I18nContent.translations_hash(:es)["great"]).to be nil + end + + it "gets new translations after values are cached" do + expect(I18nContent.translations_hash(:en)["great"]).to eq "Custom great" + + create(:i18n_content, key: "amazing", value_en: "Custom amazing") + + expect(I18nContent.translations_hash(:en)["great"]).to eq "Custom great" + expect(I18nContent.translations_hash(:en)["amazing"]).to eq "Custom amazing" + end + + it "gets the updated translation after values are cached" do + expect(I18nContent.translations_hash(:en)["great"]).to eq "Custom great" + + content.update!(value_en: "New great") + + expect(I18nContent.translations_hash(:en)["great"]).to eq "New great" + end + + it "does not get removed translations after values are cached" do + expect(I18nContent.translations_hash(:en)["great"]).to eq "Custom great" + + I18nContent.delete_all + + expect(I18nContent.translations_hash(:en)["great"]).to be nil + end + end end