【问题标题】:Unable to order by translated column in Rails using Mobility无法使用 Mobility 通过 Rails 中的翻译列排序
【发布时间】:2018-02-11 05:55:25
【问题描述】:

此问题基于发布到 Mobility GitHub 项目的 issue

上下文

  • 导轨: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 之前所做的那样。

实际行为

我得到的是#&lt;Article::ActiveRecord_Relation:0x233686c&gt;。如果我然后尝试使用@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)

...返回#&lt;#&lt;Mobility::Backends::ActiveRecord::Table::QueryMethods:0x00000000050a86d8&gt;:0x286c3e0&gt;,当我尝试将其转换为数组时,我得到了同样的结果:

  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 子句中使用翻译字段,但它目前不支持在 Active Record 查询的 order 子句中使用它们。

解决方法尝试

1。引用order子句中的翻译表

根据gem作者的反馈,我尝试了查询:

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

... 返回一个#&lt;#&lt;Mobility::Backends::ActiveRecord::Table::QueryMethods&gt;&gt; 对象,而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。为翻译表添加joinsincludes 子句

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

此查询再次返回一个#&lt;#&lt;Mobility::Backends::ActiveRecord::Table::QueryMethods&gt;&gt; 对象,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

所以……

接下来我应该尝试什么?

【问题讨论】:

  • 你能发布你的数据库架构吗?您的文章表中有视图列吗?

标签: ruby-on-rails mobility


【解决方案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')

【讨论】:

  • 做到了!感谢您的及时回复。 ?
  • 我认为这适用于其他 AR 子句,例如 select?
  • 是的,article_translations.views 是实际的表/列,因此应该可以正常使用任何 AR 方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
  • 2015-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多