Rails-加入活动记录关系

时间:2018-10-09 15:30:20

标签: ruby-on-rails ruby rails-activerecord

我正在尝试通过https://guides.rubyonrails.org/active_record_querying.html#specifying-conditions-on-the-joined-tables

我有一个ImageCollection类,其状态可以为“活动”。此类属于一个Image,该Image具有一个名为“ workflow_state”的属性。

我有以下可行的方法,但要花几秒钟才能完成:

def self.published
  where(status: STATUS_ACTIVE).select { |x| x.image.workflow_state == Publishable::Meta.published_key }
end

以下内容无效:

scope :published, lambda {
  where(status: STATUS_ACTIVE).joins(:image).where(
    'image.workflow_state = ?', Publishable::Meta.published_key
  )
}

并返回:

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

我很困惑,因为图像表具有工作流程状态

非常感谢您的帮助

2 个答案:

答案 0 :(得分:2)

如果您使用纯SQL,则应使用复数表名。

更改:将image.workflow_state更改为images.workflow_state

答案 1 :(得分:2)

  

我有以下可行的方法,但要花几秒钟才能完成:

来自self.published方法的查询将提取所有带有status: STATUS_ACTIVE的记录,然后扫描结果数组,以获取给出image.workflow_state的那些记录。因此,它获取将被select丢弃的结果,这是浪费资源。更糟糕的是,它为每一行创建一个ActiveRecord对象,并向数据库发出附加请求以获取其image关联。这是臭名昭著的N + 1 pattern problem

要解决此问题,您需要将查询重写为

  joins(:image).where(status: STATUS_ACTIVE, images: { workflow_state: Publishable::Meta.published_key } )