2016-09-29 3 views
1

Я знаю, что это должно быть просто, но я действительно потерян.Rails 4 - значения сумм, сгруппированные по внешнему ключу

Три модели: Работа, задачи и операции, как указано ниже:

Job 
has_many :tasks 

Task 
belongs_to :job 
belongs_to :operation 

Operation 
has_many :jobs 

Job имеет атрибут, total_pieces, который говорит мне, сколько частей вам нужно. Для каждого Job вы можете добавить номер Tasks, который может принадлежать разным Operations (резка, сверление и т. Д.), И для каждой задачи вы можете установить несколько штук. Я не знаю заранее, сколько Operations понадобится для одного Job, но мне нужно предупредить пользователя о количестве оставшихся частей для этого Operation, когда вставляется новый Task.

сотворим пример:

Job 1: total_pieces=100 
- Task 1: operation 1(cutting), pieces=20 
- Task 2: operation 1(cutting), pieces=30 
- Task 3: operation 2(drilling), pieces=20 

Мне нужно, чтобы предупредить пользователя о том, что они по-прежнему нужно вырезать 50 штук и пробурить 80. Гипотетически, если я добавлю:

- Task 4: operation 3(bending), pieces=20 

Мне нужно предупредить пользователя о том, что им также необходимо сгинуть 80 штук.

До сих пор я удался перечислить все виды Operations для каждого Job с помощью map, но теперь мне нужно суммировать все части Task с тем же Operation типа в Job, и только для тех, кто Operations в настоящее время Tasks, принадлежащих этому Job.

Есть ли способ сделать это, используя map? Или мне нужно написать запрос вручную?

EDIT: это то, что мне удалось исправить в настоящий момент.

Метод operations_applied Иова дает мне список идентификаторов для всех Operations USEND в Tasks очередей для Job.
Тогда другой способ, pieces_remaining for(operation), дает мне оставшиеся кусочки для одного operation.
Наконец, в Job Мне нужно, я пробовал все operations_applied все pieces_remaining_for.
Я знаю, что это не особенно элегантно, но пока это работает, любые идеи для улучшения этого? Спасибо.

ответ

0

Если я не недопонимаю, делать то, что вы хотите делать с map, невозможно, так как карта всегда относится к arr.size == arr.map {...}.size, и вы хотите, чтобы reduce вашего массива.

Что вы могли бы сделать что-то вроде этого:

job = Jobs.first 

operation_pieces = {} 
job.tasks.each do |task| 
    operation_pieces[task.operation.id] ||= { operation: task.operation } 
    operation_pieces[task.operation.id][:pieces] ||= 0 
    operation_pieces[task.operation.id][:pieces] += task.pieces 
end 

Теперь operation_pieces содержит сумму pieces для работы с id соответствующего индекса. Но я уверен, что есть более элегантный вариант, чтобы сделать это;)

EDIT: изменил пример кода на хэш

EDIT: а вот более элегантный вариант:

job = Jobs.first 
job.tasks 
    .group_by(&:operation) 
    .map { |op, tasks| 
     { op => tasks.sum(&:pieces) } 
    } 

group_by группирует ваш массив задач с помощью задачи (возможно, вам нужно использовать group_by { |t| t.operation } вместо этого, я не уверен), а внутри map после этого суммируется pieces каждой задачи с той же операцией. Наконец, вы получите хэш типа OPERATION => PIECES_SUM (INTEGER).

+0

Спасибо, это намного лучше, чем мое исправленное решение! –

0

Я полагаю, следующие переменные, необходимые для запроса,

атрибуты Задача: number_of_pieces, работы: имя, Операция: имя

Job.joins("LEFT JOIN tasks ON jobs.id = tasks.job_id").joins("LEFT JOIN operations ON operations.id = tasks.operation_id").select(" SUM(tasks.number_of_pieces) as number_of_pieces, operations.name, jobs.name").group("operations.id, jobs.id") 

Это будет список всех рабочих мест и суммы штук, необходимых для каждой операции под ним.

, если у вас есть job_id для вас, чтобы список операций и частей, а затем использовать код, приведенный ниже,

Job.find(params[:job_id]).joins("LEFT JOIN tasks ON jobs.id = tasks.job_id").joins("LEFT JOIN operations ON operations.id = tasks.operation_id").select(" SUM(tasks.number_of_pieces) as number_of_pieces, operations.name, jobs.name").group("operations.id, jobs.id") 

пожалуйста, положить в комментариях, если ваша потребность какие-либо объяснения.

+0

Спасибо, но я надеялся избежать использования SQL ... см. Мое редактирование для моего дальнейшего подхода к проблеме –

+0

Я предполагаю, что для этого вам придется реорганизовать структуру базы данных. Работа и операция не имеют отношения между ними. Поэтому достичь этого без SQL-запросов невозможно. –