Neil Neil - 2 months ago 10
Ruby Question

Rails scopes with hash syntax

Here are my two models:

class Author < ApplicationRecord
has_many :articles
end

class Article < ApplicationRecord
belongs_to :author
scope :articles_by_author, ->(author_id) {joins(:author).where(author: {id: author_id})}
end


I am trying to get the
Article.articles_by_author(id)
scope to work. Basically: It should return all the articles for a particular Author.

Here is what happens:

First I grab an author:

author = Author.first


Then I run the query:

Article.articles_by_author(author)


The generated SQL seems right:

SELECT "articles".*
FROM "articles"
INNER JOIN "authors"
ON "authors"."id" = "articles"."author_id"
WHERE "author"."id" = 1


But it errors out with the following:


ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: author.id: SELECT "articles".* FROM "articles" INNER JOIN "authors" ON "authors"."id" = "articles"."author_id" WHERE "author"."id" = 1


What am I messing up within this scope? I want to keep the hash syntax within this scope.

Answer

In joins/includes you can use model names, but in where clause you should use database table name, thus plural authors:

scope :articles_by_author, lambda { |author_id|
  joins(:author).where(authors: { id: author_id })
}

P.S. I've styled your code a bit to meet (Rubocop's) conventions :)

P.P.S. Isn't it easier (having that we know author_id) to just go with:

Author.find(author_id).articles # ? :)