Невозможно сделать заказ по переведенному столбцу в Rails, используя Mobility

Этот вопрос основан на проблеме, опубликованной в проекте Mobility GitHub.

контекст

  • Rails: 5.0.6
  • Мобильность: 0.4.2 (с бэкэндом стола)

Я работаю с таблицей статей, которая поддерживает несколько типов статей (например, пост в блоге, тематическое исследование, статья базы знаний). Эта таблица содержит столбец для отслеживания количества просмотров статьи - целочисленный столбец, который увеличивается каждый раз, когда show действие призвано к статье.

При реализации переводов для этих статей я хочу отслеживать количество просмотров для каждого перевода отдельно, а не для основного объекта статьи. Чтобы достичь этого, я включил views свойство как одно из переведенных свойств моего объекта:

class Article < ApplicationRecord
  include Taggable
  include PgSearch

  translates :title, type: :string
  translates :subtitle, type: :text
  translates :body, type: :text
  translates :views, type: :integer

  multisearchable :against => [:title, :subtitle, :body]

  has_and_belongs_to_many :products

  attachment :hero_image, content_type: %w(image/jpeg image/png image/gif)

  validates :title, :body, :posted_on, presence: true

  scope :current, -> { where 'posted_on < ?', Date.tomorrow }
  scope :news_articles, -> { where type: ['BlogPost', 'CaseStudy'] }

  def log_view(by = 1)
    self.views ||= 0
    self.views += by
    self.save(touch: false)
  end

  def to_param
    "#{id} #{title}".parameterize
  end

  def published?
    posted_on < Date.tomorrow
  end
end

Ожидаемое поведение

В моем контроллере я хочу перечислить десятку самых просматриваемых статей, которые я получаю с помощью этого запроса:

@top_articles = Article.current.news_articles.order(views: :desc, posted_on: :desc).limit(10)

Я ожидаю получить множество статей, как я делал до реализации Mobility.

Фактическое поведение

Вместо этого я получаю #<Article::ActiveRecord_Relation:0x233686c>, Если я тогда попытаюсь преобразовать это в массив с @top_articles.to_aЯ получаю эту ошибку:

  Article Load (0.7ms)  SELECT  "articles".* FROM "articles" WHERE (posted_on < '2018-02-11') AND "articles"."type" IN ('BlogPost', 'CaseStudy') ORDER BY "articles"."views" DESC, "articles"."posted_on" DESC LIMIT $1  [["LIMIT", 10]]
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column articles.views does not exist
LINE 1: ...les"."type" IN ('BlogPost', 'CaseStudy') ORDER BY "articles"...
                                                             ^
: SELECT  "articles".* FROM "articles" WHERE (posted_on < '2018-02-11') AND "articles"."type" IN ('BlogPost', 'CaseStudy') ORDER BY "articles"."views" DESC, "articles"."posted_on" DESC LIMIT $1
from /usr/local/bundle/gems/activerecord-5.0.6/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `async_exec'

Изменение запроса на включение i18n:

@top_articles = Article.i18n.current.news_articles.order(views: :desc, posted_on: :desc).limit(10)

... возвращается #<#<Mobility::Backends::ActiveRecord::Table::QueryMethods:0x00000000050a86d8>:0x286c3e0>и когда я пытаюсь преобразовать это в массив, я получаю то же самое:

  Article Load (0.7ms)  SELECT  "articles".* FROM "articles" WHERE (posted_on < '2018-02-11') AND "articles"."type" IN ('BlogPost', 'CaseStudy') ORDER BY "articles"."views" DESC, "articles"."posted_on" DESC LIMIT $1  [["LIMIT", 10]]
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column articles.views does not exist
LINE 1: ...les"."type" IN ('BlogPost', 'CaseStudy') ORDER BY "articles"...
                                                             ^
: SELECT  "articles".* FROM "articles" WHERE (posted_on < '2018-02-11') AND "articles"."type" IN ('BlogPost', 'CaseStudy') ORDER BY "articles"."views" DESC, "articles"."posted_on" DESC LIMIT $1
from /usr/local/bundle/gems/activerecord-5.0.6/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `async_exec'

Оказывается, в то время как Mobility поддерживает использование переведенных полей в where пункт, в настоящее время он не поддерживает их в order предложение запроса Active Record.

Попытки обойти

1. Ссылка на таблицу перевода в order пункт

Основываясь на отзывах автора драгоценного камня, я попробовал запрос:

Article.i18n.current.news_articles.order('article_translations.views desc', 'articles.posted_on desc')

... который возвращает #<#<Mobility::Backends::ActiveRecord::Table::QueryMethods>> объект и to_a возвращает эту ошибку:

ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "article_translations"
LINE 1: ...les"."type" IN ('BlogPost', 'CaseStudy') ORDER BY article_tr...
                                                             ^
: SELECT  "articles".* FROM "articles" WHERE (posted_on < '2018-02-12') AND "articles"."type" IN ('BlogPost', 'CaseStudy') ORDER BY article_translations.views desc, articles.posted_on desc LIMIT $1
from /usr/local/bundle/gems/activerecord-5.0.6/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `async_exec'

2. Добавить joins или же includes пункт для таблицы перевода

Article.i18n.joins(:article_translations).order('article_translations.views desc', 'articles.posted_on desc').limit(10)

Этот запрос, опять же, возвращает #<#<Mobility::Backends::ActiveRecord::Table::QueryMethods>> объект и to_a результаты в:

ActiveRecord::ConfigurationError: Can't join 'Article' to association named 'article_translations'; perhaps you misspelled it?
from /usr/local/bundle/gems/activerecord-5.0.6/lib/active_record/associations/join_dependency.rb:231:in `find_reflection'

3. Добавить has_many :article_translations моделировать

Добавление отношения к модели возвращает эту ошибку:

uninitialized constant Article::ArticleTranslation

Так…

Что я должен попробовать дальше?

1 ответ

Решение

ОБНОВИТЬ

Упорядочение по переведенным атрибутам теперь поддерживается начиная с версии 0.8.0/

Просто сделай это:

Article.i18n.current.news_articles.
  order(:views => :desc, :'articles.posted_on' => :desc)

и Mobility все обработает (вам не нужно присоединяться к таблице перевода и т. д.)

ОРИГИНАЛЬНЫЙ ОТВЕТ

Вы были правы, что вам нужно присоединиться к таблице переводов, но ассоциация называется translationsне article_translations,

В любом случае, есть метод join_translations который присоединяется к таблице перевода, так что это должно работать:

Article.i18n.
  current.
  news_articles.
  join_translations.
  order('article_translations.views desc', 'articles.posted_on desc')
Другие вопросы по тегам