Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to order by translated column #169

Closed
partydrone opened this issue Feb 10, 2018 · 3 comments
Closed

Unable to order by translated column #169

partydrone opened this issue Feb 10, 2018 · 3 comments

Comments

@partydrone
Copy link

partydrone commented Feb 10, 2018

Context

  • Rails: 5.0.6
  • Mobility: 0.4.2

I'm working with an articles table that supports multiple article types (e.g., blog post, case study, knowledge base article). This table includes a column to track the number of times an article is viewed—an integer column that increments every time a show action is called for an article.

In implementing translations for these articles, I want to track the number of views for each translation individually, not for the main article object. In an effort to achieve this, I included the views property as one of the translated properties on my object:

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

Expected Behavior

In my controller, I want to list the top ten most viewed articles, which I get with this query:

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

I expect to receive an array of articles, as I did before implementing Mobility.

Actual Behavior

What I get instead is #<Article::ActiveRecord_Relation:0x233686c>. If I then try to convert that to an array with @top_articles.to_a, I get this error:

  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'

Changing the query to include i18n:

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

… returns #<#<Mobility::Backends::ActiveRecord::Table::QueryMethods:0x00000000050a86d8>:0x286c3e0>, and when I try to convert that to an array, I get the same thing:

  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'

I haven't tried ordering by any other translated field, so I don't know if it has something to do with the fact that this particular one is an integer (not a :string or :text type as shown in your documentation), or if Mobility only supports where clauses and not order clauses.

@shioyama
Copy link
Owner

or if Mobility only supports where clauses and not order clauses.

This is in fact the case - Mobility does not support order clauses (currently at least).

Looks like you're using the table backend, in which case I believe this would work:

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

This won't work for other backends of course.

Also, the type option is ignored for all backends other than the KeyValue backend. I think I need to change the readme to make this more obvious, many people seem to include it in their examples with other backends. In this case, type: :integer does absolutely nothing; the type of the column is determined by the actual column (i.e. article_translations.views, which I assume is an integer column).

@shioyama
Copy link
Owner

Closing this, if you encounter any other issues please post to stackoverflow with the mobility tag, unless it seems to be an actual bug, in which case posting an issue is the right thing to do.

@shioyama
Copy link
Owner

Created an issue in #170 to make it clearer that type is only required for the KeyValue backend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants