0

I have a model Defect with attribute found_in. I have a hash test_phases whose keys are various test phases and whose value is an array of found_in values. Is there a way to group the Defect by test_phases? something like Defect.group_by(?test_phases)?.

The code I'm using is ugly

defects = {}
test_phases.each do |test_phase, found_ins|
  defects[test_phase] ||= Defect.where(found_in: found_ins].all
end
user2371769
  • 47
  • 1
  • 5

2 Answers2

1

You don't need to group, since you are iterating a hash (no duplicate keys), the output hash won't have multiple elements by key. Simply use map + Hash (or mash for Facets connoisseurs):

defects = Hash[test_phases.map do |test_phase, found_in_values|
  [test_phase, Defect.where(found_in: found_in_values)]
end]
tokland
  • 66,169
  • 13
  • 144
  • 170
  • Iterating over the hash would result in n sql queries, where n is the number of keys in test_phases. I was hoping there's a way to do 1 sql query, much like Defect.select('found_in', count(id) as backlogs).group('found_in'). – user2371769 Jul 30 '13 at 21:33
  • Yes, that will issue N queries. Not really sure there is a way in pure AR to do it with 1 query. – tokland Jul 30 '13 at 21:52
  • Is there a way to pass an array of keys to a hash? For example, would this be doable: defects = Defect.select('found_in', count(id) as backlogs.group('found_in'). test_phases.each do |test_phase, found_in_values| test_phase_backlogs = defects[found_in_values]? – user2371769 Jul 30 '13 at 22:00
0

I solved this by creating a TestPhase model with a join table DefectFound

test_phase.rb:
    has_many :defect_founds

defect_found.rb:
    belongs_to :test_phase

defect.rb:
    belongs_to :defect_found, foreign_key: :found_in, primary_key: :name # defect_found.name = defect.found_in
    has_one :test_phase, through: :defect_found

controller:
    @defects = Defect.includes(:test_phase).select('found_in, COUNT(id) as backlog').group(:found_in).group_by(&:test_phase)

view:
    %table
      - @defects.each do |test_phase, backlogs|
        %tr
          %td= test_phase.name if test_phase.present?
          %td= backlogs.map(&:backlog).inject(:+)
user2371769
  • 47
  • 1
  • 5