3

在我的 rails 4 项目中,我有以下表格 在此处输入图像描述

在这个SO question中,我搜索了一个 SQL 查询来获取实际项目状态 id = XX 的项目。实际上,我的意思是具有 max(created_at) 的那个。

我的查询得到了答案

select p.* from projects p
     left join projects_status_projects psp on (psp.project_id = p.id)
     where created_at = (select max(created_at) from projects_status_projects 
           where project_id = p.id)    
     and project_status_id = XX

我的模型已定义

class Project < ActiveRecord::Base
   has_many :projects_status_projects
   has_many :projects_statuses, :through => :projects_status_projects
end

class ProjectStatus < ActiveRecord::Base
   has_many :projects_status_projects
   has_many :projects, :through => :projects_status_projects
end

class ProjectsStatusType < ActiveRecord::Base
   belongs_to :project
   belongs_to :project_status
end

在我的项目模型中,我有以下方法

def self.with_status(status)
   joins(:projects_status_projects)
       .where('projects_status_projects.created_at = (select max(created_at) from 
                    projects_status_projects where project_id = p.id)')
       .where('projects_status_projects.project_status_id = ?', status)
end

虽然查询是正确的,但收到的结果经过了很好的过滤,我发现这个解决方案很糟糕而且一点也不优雅。

有没有办法用范围获得相同的结果?

谢谢你的帮助。

4

3 回答 3

1

What do you think of

scope :with_status, -> (status) { 
   ProjectsStatusType.where(:project_status_id, status).order(:created_at).last.project 
}

EDIT based on comments :

As sockmonk said, scopes should be chainable. Here is a cleaner way to do it, which also fix the problem if no project is found.

# ProjectStatusType model
scope :with_ordered_status, -> (status) { 
   where(:project_status_id, status).order(:created_at)
}

# Project model
def self.find_by_status(status)
  project_statuses = ProjectsStatusType.with_ordered_status(status)
  project_statuses.any? ? project_statuses.last.project : nil
end
于 2013-10-08T15:50:04.920 回答
0

怎么样?

scope :with_status, ->(status = "default_status") {
    joins(:projects_status_projects).
    where('projects_status_projects.project_status_id = ?', status).
    order("projects_status_projects.created_at DESC").first
  }
于 2013-10-08T15:44:48.383 回答
0
scope :with_status, ->(status = "default_status") {
  joins(:projects_status_projects)
  .where('projects_status_projects.project_status_id = ?', status)
  .order("projects_status_projects.created_at DESC")    
}

当你调用它时,你会想要在它的末尾添加一个“.first”;不能将 .first 包含在范围本身中,因为这会使它无法链接。

于 2013-10-08T15:52:27.677 回答