2

この質問は、Mobility GitHub プロジェクトに投稿された問題に基づいています。

環境

  • レール: 5.0.6
  • Mobility : 0.4.2 (テーブル バックエンドあり)

複数の記事タイプ (ブログ投稿、ケース スタディ、ナレッジ ベース記事など) をサポートする記事テーブルを使用しています。このテーブルには、記事が表示された回数を追跡するための列 (記事showに対してアクションが呼び出されるたびに増加する整数列) が含まれています。

これらの記事の翻訳を実装する際に、メインの記事オブジェクトではなく、各翻訳のビュー数を個別に追跡したいと考えています。これを実現するためviewsに、オブジェクトの翻訳済みプロパティの 1 つとしてプロパティを含めました。

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

予想される行動

私のコントローラーでは、次のクエリで取得する、最も閲覧された記事のトップ 10 をリストしたいと考えています。

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

モビリティを実装する前と同様に、一連の記事を受け取ることを期待しています。

実際の動作

代わりに得られるのは#<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

回避策の試み

order1.節で翻訳表を参照する

gem の作成者からのフィードバックに基づいて、次のクエリを試しました。

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'

joins2. 変換テーブルにorincludes句を追加します

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

それで…</h2>

次に何を試せばいいですか?

4

1 に答える 1

2

アップデート

バージョン 0.8.0/ から、翻訳された属性による順序付けがサポートされるようになりました。

これを行うだけです:

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

モビリティがすべてを処理します (変換テーブルに参加する必要はありません)。

元の答え

翻訳テーブルに参加する必要があることは正しかったのですが、関連付けの名前translationsは ではなくarticle_translationsです。

いずれにせよ、join_translations変換テーブルを結合するメソッドがあるため、これは機能するはずです。

Article.i18n.
  current.
  news_articles.
  join_translations.
  order('article_translations.views desc', 'articles.posted_on desc')
于 2018-02-11T06:06:06.967 に答える