Class: ReportingEntry

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

Overview

This class represents a single reporting entry. Casting for numerical values and a ‘+’ for the addition of different object is included.

Constant Summary collapse

SUMMABLE_INT_FIELDS_REGEXP =

These constants define fields which are casted to integers/float in the accessor. Also these fields are added when adding two SuperReportingEntries.

DON’T USE THIS FOR IDs (e.g. ad_id)

/OVERWRITE_THIS_IN_SUBCLASS/
SUMMABLE_FLOAT_FIELDS_REGEXP =
/OVERWRITE_THIS_IN_SUBCLASS/
NOT_SUMMABLE_FIELDS =

Columns listed in this array are explicitely not summable

%w()

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = {}) ⇒ ReportingEntry

Standard constructor takes attributes as hash (like OpenStruct)



21
22
23
# File 'lib/reporting/reporting_entry.rb', line 21

def initialize(attributes = {})
  @attributes = HashWithIndifferentAccess.new(attributes)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_id, *args) ⇒ Object

Offers an OpenStruct like access to the values stored in @attributes Uses the information from SUMMABLE_*_FIELDS_REGEXP to cast to numerical values.



28
29
30
31
32
33
34
# File 'lib/reporting/reporting_entry.rb', line 28

def method_missing(method_id, *args)
  return self.send("lazy_#{method_id}", *args) if self.respond_to?("lazy_#{method_id}")
  if @attributes.has_key?(method_id) || method_id.to_s =~ summable_fields_regexp
    return cast(method_id, @attributes[method_id])
  end
  super(method_id, *args)
end

Instance Attribute Details

#attributesObject (readonly)

The raw attributes hash



6
7
8
# File 'lib/reporting/reporting_entry.rb', line 6

def attributes
  @attributes
end

Class Method Details

.composite(entries) ⇒ Object

Returns a composite element which lazily sums up the summable values of the children



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
# File 'lib/reporting/reporting_entry.rb', line 70

def self.composite(entries)
  public_methods         = self.instance_methods - Object.public_methods
  summable_methods       = public_methods.select { |method| method.to_s =~ summable_fields_regexp }

  klass = Class.new(self) do
    define_method(:method_missing) do |method_id, *args|
      if (method_id.to_s =~ summable_fields_regexp)
        return entries.inject(0) do |sum, entry|
          sum + entry.send(method_id, *args)
        end
      else
        return entries.first.send(method_id, *args)
      end
    end

    # Delegate all summable method calls to the children
    # by using the method_missing method
    summable_methods.each do |method_id|
      define_method(method_id) do |*args|
        self.method_missing(method_id, *args)
      end
    end
    
    # For better debuggability
    #
    define_method :inspect do
      "CompositeReportingEntry [entries: #{entries.inspect} ]"
    end
  end
  klass.new
end

Instance Method Details

#+(other) ⇒ Object

Add another SuperReportingEntry and returns the resulting entry. All attributes specified by SUMMABLE_FIELD_REGEXP are summed up. Further attributes are merged (the own values has priority).



39
40
41
# File 'lib/reporting/reporting_entry.rb', line 39

def +(other)
  return self.class.composite([self, other])
end

#is_sum_entry?Boolean

Returns true if entry is a sum entry (like returned by to_sum_entry)

Returns:

  • (Boolean)


103
104
105
# File 'lib/reporting/reporting_entry.rb', line 103

def is_sum_entry?
  return false
end

#to_sum_entryObject

Returns a ReportingEntry object with all non addable values set to nil This is thought be used for sum(mary) rows



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/reporting/reporting_entry.rb', line 45

def to_sum_entry
  subject = self
  klass = Class.new(self.class) do
    # overwrite explicitely not summable columns
    #
    subject.send(:not_summable_fields).each do |method_id|
      define_method(method_id) { nil }
    end
    
    # method missing decides if the columns is displayed or not
    #
    define_method(:method_missing) do |method_id, *args|
      (method_id.to_s =~ summable_fields_regexp) ? subject.send(method_id, *args) : nil
    end

    # yes, this actually is a sum entry ;-)
    #
    def is_sum_entry?
      return true
    end
  end
  klass.new
end