Class: Columnizer

Inherits:
Object
  • Object
show all
Defined in:
lib/columnizer.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(list, number_of_columns) ⇒ Columnizer

Returns a new instance of Columnizer.



3
4
5
6
7
8
# File 'lib/columnizer.rb', line 3

def initialize(list, number_of_columns)
  @list = Columnizer.convert_to_array(list)
  @column_count = number_of_columns
  @items_by_column = []
  columnize!
end

Class Method Details

.convert_to_array(list) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/columnizer.rb', line 76

def self.convert_to_array(list)
  truncated_list = []
  if list.respond_to?(:keys)
    keys = list.keys
    keys.each do |key|
      list[key.to_s] = list.delete(key)
    end
    list.each do |key, value|
      validate_depth(value)
      truncated_list << [key.dup, value]
    end
  else
    truncated_list = list
  end
  truncated_list
end

.truncate_list(list, range) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/columnizer.rb', line 51

def self.truncate_list(list, range)

  list = convert_to_array(list)

  first_index, last_index = range.begin, range.end
  first_item, last_item = list.flatten[first_index], list.flatten[last_index]

  list.each { |o| o.extend(IsOrIncludes) }
  list.flatten(1).each { |o| o.extend(IsOrIncludes) }
  list.flatten(2).each { |o| o.extend(IsOrIncludes) }

  first_item_index = list.index { |o| o.is_or_includes?(first_item) }
  last_item_index = list.index { |o| o.is_or_includes?(last_item) }

  last_item_container = list[last_item_index]
  if last_item_container.is_a?(Array)
     unless last_item_container[1].eql?(last_item) || last_item_container[1].last.eql?(last_item) || last_item_container[1].empty?
        last_item_index -= 1
     end
  end

  list[first_item_index..last_item_index]

end

.validate_depth(value) ⇒ Object



93
94
95
96
97
# File 'lib/columnizer.rb', line 93

def self.validate_depth(value)
  if value.respond_to?(:each) then
    value.each { |item| raise "Columns not supported for lists nested more than one level" if item.respond_to?(:keys) }
  end
end

Instance Method Details

#columnize!Object



10
11
12
13
14
# File 'lib/columnizer.rb', line 10

def columnize!
  (1..@column_count).each do |column_number|
    @items_by_column[column_number] = find_items_for_column(column_number)
  end
end

#find_items_for_column(column_number) ⇒ Object



20
21
22
23
24
25
26
27
# File 'lib/columnizer.rb', line 20

def find_items_for_column(column_number)
  zero_based_column_number = column_number-1
  return [] if item_count_by_column[zero_based_column_number]==0
  first_item_index = 0 if zero_based_column_number==0
  first_item_index ||= (item_count_by_column[0..zero_based_column_number-1]).inject(:+)
  last_item_index = first_item_index+item_count_by_column[zero_based_column_number]-1
  Columnizer.truncate_list(@list, first_item_index..last_item_index)
end

#item_count_by_columnObject



29
30
31
32
33
34
35
36
37
# File 'lib/columnizer.rb', line 29

def item_count_by_column
  item_count_by_column = []
  total_item_count = total_item_count_for_collection(@list)
  balanced_item_count = total_item_count / @column_count
  unbalanced_item_count = total_item_count % @column_count
  @column_count.times { item_count_by_column << balanced_item_count }
  item_count_by_column[-unbalanced_item_count..-1] = item_count_by_column[-unbalanced_item_count..-1].collect { |n| n+1 } if unbalanced_item_count > 0
  item_count_by_column
end

#items_for_column(column_number) ⇒ Object



16
17
18
# File 'lib/columnizer.rb', line 16

def items_for_column(column_number)
  @items_by_column[column_number]
end

#total_item_count_for_collection(list) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/columnizer.rb', line 39

def total_item_count_for_collection(list)
  item_count = 0
  list.each do |item|
    if item.is_a?(Enumerable)
      item_count += total_item_count_for_collection(item)
    else
      item_count += 1
    end
  end
  item_count
end