Reputation: 6445
I'm trying to follow through https://guides.rubyonrails.org/active_record_querying.html#specifying-conditions-on-the-joined-tables
I have a class, ImageCollection, that has a status which can be 'active'. This class belongs to one Image, which has an attribute called 'workflow_state'.
I have the following that works but takes a few seconds to execute:
def self.published
where(status: STATUS_ACTIVE).select { |x| x.image.workflow_state == Publishable::Meta.published_key }
end
The following does not work:
scope :published, lambda {
where(status: STATUS_ACTIVE).joins(:image).where(
'image.workflow_state = ?', Publishable::Meta.published_key
)
}
And returns:
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'image.workflow_state' in 'where clause': SELECT `image_containers`.* FROM `image_containers` INNER JOIN `images` ON `images`.`id` = `image_containers`.`image_id` WHERE `image_containers`.`status` = 'active' AND (image.workflow_state = 'published') ORDER BY `image.containers`.`id` ASC LIMIT 1
I'm confused as the image table has a workflow_state
Any help is greatly appreciated
Upvotes: 1
Views: 48
Reputation: 2781
I have the following that works but takes a few seconds to execute:
The query from self.published
method fetches all record with status: STATUS_ACTIVE
, and then scans the resulting array, fetching those ones which have given image.workflow_state
. So it fetches results which will be thrown away with select
, which is a waste of resources. What is worse, for every row it creates an ActiveRecord object and makes an additional request to the database to fetch its image
association. It's notorious N + 1 pattern problem.
To fix it you need to rewrite your query as
joins(:image).where(status: STATUS_ACTIVE, images: { workflow_state: Publishable::Meta.published_key } )
Upvotes: 2
Reputation: 44360
If you're using plain sql you should use pluralize table names.
Change: image.workflow_state
to images.workflow_state
Upvotes: 2