Module: Summarizer::Base::ClassMethods

Defined in:
lib/summarizer/base.rb

Overview

the methods in this module will become class methods

Instance Method Summary collapse

Instance Method Details

#find_with_sums(*args) ⇒ Object

Raises:

  • (ArgumentError)


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/summarizer/base.rb', line 20

def find_with_sums(*args)

  options = args.extract_options!

  raise ArgumentError unless args.first.nil? || args.first == :all

  # extract method specific options before call to +find+
  split_sections_on = options.delete(:split_sections_on)
   = options.delete(:section_label)

  ar = self.find(:all, options)

  class << ar
    attr_reader :total
    attr_writer :referring_class, :split_sections_on
    attr_accessor :section_label

    def each_with_sums(&block)

      @total = AddItUp.new(@referring_class)
      sub_total = AddItUp.new(@referring_class)
      previous_item = nil

      self.each_with_index do |item, index|
        class << item
          attr_writer :section_label
          def set_table_info(new_group, end_of_group, sum_group)
            @new_section = new_group
            @end_of_section = end_of_group
            @sum_section = sum_group.static if end_of_group
          end
          # Returns +true+, if this items is the first of a new section
          def new_section?
            @new_section
          end
          # Returns +true+, if this items is the last of a section
          def end_of_section?
            @end_of_section
          end
          # Returns the summarizer object of the given section
          def section_sum
            @sum_section
          end
          def 
            if @section_label.kind_of?(Proc)
              @section_label.call(self)
            elsif @section_label.kind_of?(Symbol)
              # if a Symbol is given, call the matching method
              self.send(@section_label)
            else
              raise ArgumentError.new("@section_label has class #{@section_label.class}, but must be either Proc or Symbol.")
              raise ArgumentError.new("Value of :section_label has class #{@section_label.class}, but must be either Proc or Symbol.")
            end
          end
        end

        # check, if item opens a new section in the array
        new_section = previous_item.nil? || check_for_different_sections(previous_item, item)

        # peek at the next item to see if item is the last of the section
        next_item = self.at(index + 1)

        end_of_section = next_item.nil? || check_for_different_sections(item, next_item)

        # add it up!
        @total.add(item)
        sub_total.add(item)

        # store information in item
        item.set_table_info(new_section, end_of_section, sub_total)

        item. = self.

        # yield the block
        yield item

        # reset summarizer if neccesary
        sub_total.reset if end_of_section

        # loop!
        previous_item = item
      end

      self
    end

    private
    def check_for_different_sections(a, b)
      if @split_sections_on.kind_of?(Proc)
        # evaluate Proc to check, if item is in a new section
        @split_sections_on.call(a, b)
      elsif @split_sections_on.kind_of?(Symbol)
        # if a Symbol is given, compare the return values of their functions
        a.send(@split_sections_on) != b.send(@split_sections_on)
      else
        raise ArgumentError.new("Value of :split_sections_on has class #{@split_sections_on.class}, but must be either Proc or Symbol.")
      end
    end
  end

  ar.split_sections_on = split_sections_on
  ar. = 

  # Array just wouldn't know otherwise, with class it belongs to
  ar.referring_class = self

  ar
end

#summarize(*args) ⇒ Object

macro: store the option and the attribute to summarize



13
14
15
16
17
18
# File 'lib/summarizer/base.rb', line 13

def summarize(*args)
  options = args.last.kind_of?(Hash) ? args.pop : {}

  write_inheritable_attribute 'attributes', args
  write_inheritable_attribute 'options', options
end