2015-12-22 106 views
1

我的数据库中选择子集有任务,其中有分配了涉及员工完成任务(除其他事项外)。用户使条目,它始终有一个任务。我在入口创建代码中发现一个错误,导致员工无法自动添加到作业列表中;我想编写一个迁移程序,为每个为某项任务输入条目并且没有任何条目的员工创建分配。通过优雅的属性

这是我目前的做法:

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) 
      } 
     } 

的选择到MAP到uniq的是丑陋的。我可以更优雅地做到这一点吗?值得注意的是:entry.employee是经历另一个类的委托。

编辑:我想我会回来解决这个问题;一位高级程序员将此调用重写为使用连接和采摘。

回答

0

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

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 

值得注意:

  • find_each是更适合这个查询比all.each,因为它会运行在此查询一次批量并保持系统性能。现在
  • 孤儿被分配给了,这使我们能够提供在日志中反馈的时候,我们用的地方,而不是选择运行迁移
  • 使我们的查询苗条
  • 我们可以用更简洁pluck代替笨重的map(&:employee)