1

我对移动宝石有一个简单的问题。我的模型中有一个简单的关系。假设公司有很多员工,员工有一个翻译的属性:job_function,它使用backend: :table.

class Company < ApplicationRecord
    has_many :employees
end

class Employee < ApplicationRecord
    extend Mobility

    translates :job_function, type: :string, locale_accessors: true, backend: :table
end

如果我尝试这样做:

Company.first.employees.map(&:job_function)

我得到了n+1的问题。每个 :job_function 翻译都是单独加载的。

在开始映射集合之前,如何告诉 Mobility 一次性将它们全部加载?

我在文档中找不到任何这样的例子......

4

2 回答 2

1

You can just use pluck, which is supported by Mobility:

Company.first.employees.i18n.pluck(:job_function)
于 2021-09-25T14:09:07.253 回答
-1

您可以将includes员工 + 他们的 job_function 翻译,这是n+2 查询

这是我的演示,产品模型包含许多版本模型,这些模型已经为名称属性设置了移动性,分别对应于您的公司、员工、工作职能。

class Version < ApplicationRecord
  belongs_to :product

  extend Mobility
  translates :name, locale_accessors: [:en, :ja], backend: :table
end

class Product < ApplicationRecord
 has_many :versions

 has_many :translation_versions, -> { 
   i18n{name.not_eq(nil)}
   .select("versions.*, 
            version_translations_#{Mobility.locale}.name AS translate_name")
  }, class_name: "Version"
end

使用默认语言环境:en

Product.includes(:translation_versions).first.translation_versions
   .map(&:translate_name)

# SELECT "products".* FROM "products" ...
# SELECT versions.*, version_translations_en.name AS translate_name 
#  FROM "versions" LEFT OUTER JOIN "version_translations" "version_translations_en" 
#  ON "version_translations_en"."version_id" = "versions"."id" 
#  AND "version_translations_en"."locale" = 'en' 
#  WHERE "version_translations_en"."name" IS NOT NULL AND "versions"."product_id" = ? ...

# => ["v1", "v2"]

使用语言环境:ja

Mobility.locale = :ja
Product.includes(:translation_versions).first.translation_versions
   .map(&:translate_name)
# ...
# => ["ja v1", "ja v2"]

所以只有一个查询。

如果您的backend设置是 KeyValue,翻译表不仅会分隔localetype字符串,文本,...),而且您已经决定了属性的类型,对吗?例如:名称:字符串。这样您仍然只需要设置动态语言环境。

class Product < ApplicationRecord
 has_many :translation_versions, -> { 
  i18n{name.not_eq(nil)}
   .select("versions.*, 
     Version_name_#{Mobility.locale}_string_translations.value AS translate_name")
  }, class_name: "Version"
end

查询与上述相同。

当然,您可以translation_versions更一般地通过将其分成一个模块,用Version类名,name目标属性替换并制作一个类似于translation_#{table_name}.

于 2021-09-25T10:54:03.900 回答