Searching translated attributes yields "column does not exist" error
- What were you trying to do?
Our app's content is stored in DB and translated using Mobility. For instance a Thought
model has translates :quote
and ThoughtDashboard
has quote: Field::Text
. Listing, showing and editing the thoughts' quotes in the different languages from the admin dashboard works as expected (*). Behind the scenes Mobility automatically generates the required getter and setter methods which it maps to ActiveRecord associations.
When using the administrate search box, records whose searchable attributes contain the provided text should be returned, whether these attributes are translated or not.
- What did you end up with (logs, or, even better, example apps are great!)?
This error is raised when performing a search:
ActionView::Template::Error: PG::UndefinedColumn: ERROR: column thoughts.quote does not exist
LINE 1: ...me" AS CHAR(256))) LIKE '%thought%' OR LOWER(CAST("thoughts"...
^
It appears that because the attribute is Field::Text
, Administrate assumes that the data is stored in a text column in the same table. However the data may well be stored in the same table but using JSON, or in a key-value polymorphic table, or (as in our case) in a belongs-to table, or why not even in other ways.
Although Mobility has various backend strategies, it provides a unified querying API, e.g. thought.quote
"just works" and shields us from worrying about "implementation details" regarding how the translation is actually stored. This is why I can simply rely on Field::Text
in the dashboard to display and edit the attribute. Unfortunately this assumption no longer holds when performing a search.
Exact-match searches can be done with Thought.i18n.where(quote: "blah")
and partial case-insensitive matches with Arel predicates: Thought.i18n { quote.matches("%thought%") }
. Mobility also has an integration with Ransack allowing for queries like Thought.ransack(quote_cont: 'foo').result
. An important improvement would be having real full-text search (e.g. using pg_search or searchkick) where fuzzy matches are returned by order or decreasing relevance. Maybe it would be too much for Administrate to do all of this out of the box, but making it possible by plugging in an API would be great. Or can this somehow already be done by overriding some methods?
- What versions are you running?
- Rails 6.1.0.rc1
- administrate master 1a35ab21
- mobility 1.0.0.rc1
(*) As in the main app, the admin routes are scoped to set the proper I18n.locale
, and there is a language switcher.