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:
- A
sluggable
can have a different amount ofslugs
in each language (there isn't a direct mapping between a slug in one language and a slug in another); - 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); - One single join is required (takes care of both the translation and the slug<->post relationship);
- 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.