この質問は、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
回避策の試み
order
1.節で翻訳表を参照する
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'
joins
2. 変換テーブルに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>
次に何を試せばいいですか?