Rails 全球化 - 按语言环境预加载特定翻译
Rails Globalize - Eager Load Specific Translations by Locale
所以我在 Rails 中有一个模型,安装并配置了 globalize
:
model.rb
class Model < ApplicationRecord
include TranslationWrites
translates :column
...
end
我只想预先加载“英语”和“法语”翻译,以防止循环时出现 N+1 查询问题。我尝试了几种方法,但查询无法按预期工作。这是我尝试过的:
Model.includes(:translations).first
执行以下 SQL:
Model Load (...)
SELECT * FROM models ORDER BY id ASC LIMIT 1
Model::Translations Load (...)
SELECT * FROM model_translations WHERE model_translations.model_id = 1
这非常适合预先加载所有翻译,但我只想要“英语”和“法语”。我试过这段代码:
Model.includes(:translations).where(translations: { locale: ['en', 'fr'] }).first
运行如下错误SQL:
Model Load (...)
SELECT * FROM models LEFT OUTER JOIN model_translations ON model_translations.model_id = models.id WHERE translations.locale IN ('en', 'fr')
ActiveRecord::StatementInvalid (Mysql2::Error: Unknown column 'translations.locale' ...)
如您所见,条件预加载(如 on this tutorial 所示)似乎不起作用...
最后,Globalize 有 with_translations(['en', 'fr'])
方法,但是 Model
的范围只返回那些 有 指定的翻译.我需要那些模型 ,不管他们是否有“英语”或“法语”。如果你熟悉Laravel,那就是with()
和whereHas()
的区别:
// Returns all `Model` instances, and each `$model->translations` will have `en` and `fr` only.
Model::with(['translations' => function($query) {
$query->whereIn('locale', ['en', 'fr'])
})->get();
// Only returns `Model` instances that have `en` or `fr` translations, but `$model->translations` will include all translations
$models = Model::whereHas('translations', function($query) {
$query->whereIn('locale', ['en', 'fr'])
})->get();
有人遇到过这个吗?我需要一种有效的方法来只为数据库中的每个模型加载英语和法语翻译,而不管翻译是否实际存在。
一般来说,在您的 .where
方法中,您应该使用真实的 table 名称,而不是模型之间关系的名称,因此尝试使用:
Model.includes(:translations).where(model_translations: { locale: ['en', 'fr'] }).first
所以我在 Rails 中有一个模型,安装并配置了 globalize
:
model.rb
class Model < ApplicationRecord
include TranslationWrites
translates :column
...
end
我只想预先加载“英语”和“法语”翻译,以防止循环时出现 N+1 查询问题。我尝试了几种方法,但查询无法按预期工作。这是我尝试过的:
Model.includes(:translations).first
执行以下 SQL:
Model Load (...)
SELECT * FROM models ORDER BY id ASC LIMIT 1
Model::Translations Load (...)
SELECT * FROM model_translations WHERE model_translations.model_id = 1
这非常适合预先加载所有翻译,但我只想要“英语”和“法语”。我试过这段代码:
Model.includes(:translations).where(translations: { locale: ['en', 'fr'] }).first
运行如下错误SQL:
Model Load (...)
SELECT * FROM models LEFT OUTER JOIN model_translations ON model_translations.model_id = models.id WHERE translations.locale IN ('en', 'fr')
ActiveRecord::StatementInvalid (Mysql2::Error: Unknown column 'translations.locale' ...)
如您所见,条件预加载(如 on this tutorial 所示)似乎不起作用...
最后,Globalize 有 with_translations(['en', 'fr'])
方法,但是 Model
的范围只返回那些 有 指定的翻译.我需要那些模型 ,不管他们是否有“英语”或“法语”。如果你熟悉Laravel,那就是with()
和whereHas()
的区别:
// Returns all `Model` instances, and each `$model->translations` will have `en` and `fr` only.
Model::with(['translations' => function($query) {
$query->whereIn('locale', ['en', 'fr'])
})->get();
// Only returns `Model` instances that have `en` or `fr` translations, but `$model->translations` will include all translations
$models = Model::whereHas('translations', function($query) {
$query->whereIn('locale', ['en', 'fr'])
})->get();
有人遇到过这个吗?我需要一种有效的方法来只为数据库中的每个模型加载英语和法语翻译,而不管翻译是否实际存在。
一般来说,在您的 .where
方法中,您应该使用真实的 table 名称,而不是模型之间关系的名称,因此尝试使用:
Model.includes(:translations).where(model_translations: { locale: ['en', 'fr'] }).first