0

I'm building a sorted hash for use in a grouped select in a rails app. I am not using ActiveRecord. Is there a more efficient or cleaner way than this?

def for_select
  select_list = {}
  Department.all.each do |dept|
    select_list[dept.top_level_department_cn] ||= []
    select_list[dept.top_level_department_cn] << [dept.cn, dept.sorid]
  end
  select_list.each_value { |select_options| select_options.sort_by!(&:first) }
             .sort
             .to_h
end
HarlemSquirrel
  • 8,966
  • 5
  • 34
  • 34

2 Answers2

1
def for_select
  Department.all
  .sort
  .group_by(&:top_level_department_cn)
  .each_value{|v| v.map!{|dept| [dept.cn, dept.sorid]}.sort_by!(&:first)}
end
sawa
  • 165,429
  • 45
  • 277
  • 381
1

Another solution:

def for_select
  # @see: https://stackoverflow.com/questions/2698460#answer-28916684
  select_list = Hash.new { |h, k| h[k] = [] }

  Department.all
    .map { |d| [d.top_level_department_cn, [d.cn, d.sorid]] }
    .sort
    .each { |top_level_cn, data| select_list[top_level_cn] << data }

  select_list
end
romainsalles
  • 2,051
  • 14
  • 17
  • I didn't know I could create a hash with default values. That is very cool! However, in the linked SO answer, the author recommends `Hash.new([].freeze)` and I do like that better. – HarlemSquirrel Aug 03 '17 at 14:02
  • That's right, but in this case you'll have to instantiate a new array each time: `.each { |top_level_cn, data| select_list[top_level_cn] += [data] }`, which is less intuitive in my point of view (you have to read this like this: `.each { |top_level_cn, data| select_list[top_level_cn] = select_list[top_level_cn] + [data] }`) – romainsalles Aug 03 '17 at 14:16