【问题标题】:Return a query with nested results with Rails ActiveRecord使用 Rails ActiveRecord 返回带有嵌套结果的查询
【发布时间】:2014-10-28 22:55:19
【问题描述】:

我正在尝试获取我正在制作的工作流工具的活动任务列表,数据结构如下:

  • 用户
    • has_many 项目
      • has_many 子项目
        • has_many 任务
          • has_many TimeLogs

活动任务定义为具有 TimeLog 且没有“已完成”时间戳的任何任务。

我正在尝试让主页显示这个完整的结构,但只显示在某个级别具有活动任务的父结构。查询不应返回任何下方没有活动任务的用户/项目/子项目。

到目前为止我已经尝试过:

  • 对所有四个表进行连接,这会产生重复的行
  • WHERE EXISTS 语句,仅返回相关用户,但在我尝试访问其子项时不维护 WHERE 子句

有没有办法在不手动剔除 Ruby 中的数据的情况下实现这一点?

【问题讨论】:

  • 您可以将.uniq 添加到连接查询的末尾。然后 ActiveRecord 将在没有重复项的情况下进行查询。
  • 这适用于顶级用户,但是当我抓取用户的子项目时,它只会抓取所有项目。通过孩子们传递where 子句似乎很乱,所以我正在寻找一种方法来一次抓住它,也许将 ActiveRecord 查询转换为嵌套哈希?

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


【解决方案1】:

由于嵌套级别的问题,它可能相当复杂。据我了解,您想省略没有任何活动任务的用户|项目|子项目。没有简单的 sql 可以让您通过以下方式实现:

users.each do |user|
  user.active_projects.each do |project|
    ...
  end
end

相反,我会先查询任务,即@tasks = Task.includes(:subproject => [:project => :user]).where("status NOT IN ('completed')")。然后你有未完成的任务,现在你需要做的就是重新排序获取的数据,我的意思是:

@tasks = @tasks
.group_by {|t| t.subproject.project.user }
.reduce({}) do |sum, (user, tasks)|
  sum[user] ||= {}
  tasks.each do |task|
    sum[user][task.subproject.project] ||= {}
    sum[user][task.subproject.project][task.subproject] ||= []
    sum[user][task.subproject.project][task.subproject] << task 
  end
  sum
end

我没有对此进行测试,但就是这样。

【讨论】:

  • Bleh,所以最好的方法是手动构建树。我担心会是这样。感谢您提供代码示例。
【解决方案2】:

你可以根据activerecord queries documents试试这个:

user.projects.joins(subprojects: { tasks: [{ time_logs: { timestamp: 'completed'} }] })

我无法测试它,但试一试。

【讨论】:

  • 不幸的是,这是我的第一个想法,但是如果用户有多个活动任务,则 joins 会返回重复的行,正如我在 cmets 中提到的,.uniq 不适用 where子关系的子句。
猜你喜欢
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-16
  • 1970-01-01
  • 2018-09-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多