Translating Rails has_many string attribute using Mobility

346 Views Asked by At

Context

Considering a Rails 6 application with a sluggable polymorphic relation, a model's has_many collection of slugs localized to different languages can be modeled as follows:

# slugs table schema
create_table :slugs do |t|
  t.references :sluggable, polymorphic: true
  t.string :locale, null: false
  t.string :slug, null: false
  t.timestamps null: false
end
add_index :slugs, [:locale, :slug], unique: true

# app/models/slug.rb
class Slug < ApplicationRecord
  belongs_to :sluggable, polymorphic: true
end

# app/models/post.rb
class Post < ApplicationRecord
  has_many :slugs, -> { where(locale: I18n.locale).order(created_at: :desc) }, as: :sluggable
end
 
# app/models/course.rb
class Course < ApplicationRecord
  has_many :slugs, -> { where(locale: I18n.locale).order(created_at: :desc) }, as: :sluggable
end

This should meet the following requirements:

  1. A sluggable can have a different amount of slugs in each language (there isn't a direct mapping between a slug in one language and a slug in another);
  2. A constraint ensures the slugs are unique for each locale (sluggable_type could be included in the index depending on whether one wishes slugs to be unique across the application or unique within each model type);
  3. One single join is required (takes care of both the translation and the slug<->post relationship);
  4. The relation keeps its order to allow picking the "default" slug.

A post's slugs can be queried withpost.slugs. By convention the post's "default" slug would be post.slugs.first.

A post can be found by its locale and slug as follows:

Post.includes(:slugs).find_by(slugs: { "my-slug" })

Question

How to achieve an equivalent effect using the Mobility library? I already use this translation library in the rest of my app and would like to be able to query translated content in a consistent manner.

The key-value backend documentation seems to fit the bill for requirement #3, i.e. the mobility_string_translations table is a polymorphic relation which looks like it could replace the slugs table. However concerning #2, it declares a unique index across ["translatable_id", "translatable_type", "locale", "key"] so it wouldn't allow multiple slugs for a given sluggable and locale. The documentation shows how to translate attributes with a single value in each locale (e.g. a Post with a title), but not with several values (e.g. a Post with several slugs, as above).

Does Mobility support the above scenario, or can/should it be implemented with some kind of new backend?

PS: I also opened a GitHub issue.

PPS: In this SO question I also considered the possibility of storing these slugs in a JSONB array, but it is recommended against, and besides, Mobility can only translate string and text types.

0

There are 0 best solutions below