优雅地选择属性的子集

时间:2015-12-22 03:57:27

标签: ruby-on-rails

我的数据库有任务,其分配员工与任务(以及其他内容)相关联。用户创建条目,它们总是有任务。我在条目创建代码中发现了一个错误,该错误阻止员工自动添加到分配列表中;我想编写一个迁移,它将为每个为任务设置条目但没有任务的员工创建任务。

这是我目前的做法:

Task.all.each { |task|
            assigned_employees = task.assignments.map(&:employee)
            task.entries.select{ |entry| assigned_employees.exclude?(entry.employee) }.map(&:employee).uniq.each { |orphan_employee| 
                task.assignments.create(employee: orphan_employee, task: task)
            }
        }

select-to-map-to-uniq很难看。我能更优雅地做到这一点吗?

值得注意的是:entry.employee是一个通过另一个类的委托。

编辑:我想我会回来解决这个问题;一位资深程序员重写了这个使用连接和拔出的调用。

1 个答案:

答案 0 :(得分:0)

高级程序员重写了这个查询如下:

$users = Users::orderBy('items.id')->join('items', 'items.user_id', '=', 'users.id')->get();

值得注意的是:

  • find_each比all.each更适合此查询,因为它一次批量运行此查询并保持系统的性能。
  • 现在正在分配
  • 孤儿,这使我们能够在运行迁移时在日志中提供反馈
  • 使用where而不是select使我们的查询更加苗条
  • 我们可以使用更简洁的Task.find_each do |task| assigned_employees = task.task_assignments.map(&:employee_id) orphans = Timesheet.joins(:timesheet_entries). where(timesheet_entries: { id: task.timesheet_entry_ids }). where.not(timesheets: { employee_id: assigned_employees }). pluck(:employee_id).uniq puts "Found #{orphans.size} missing TaskAssignments for Task##{task.id}." if orphans.any? orphans.each do |orphan_employee_id| task.task_assignments.create(employee_id: orphan_employee_id, task: task) end end 代替笨重的pluck