Introduction
Introduction Statistics Contact Development Disclaimer Help
use yardoc for documentation - reportable - Fork of reportable required by WarV…
Log
Files
Refs
README
---
commit b94d337cd6b1aa0fc6aa285542e7c9f2ad3553e7
parent 7a999addb7eef8518d36310c56b4ca80450f3a4d
Author: Marco Otte-Witte <[email protected]>
Date: Wed, 24 Feb 2010 21:38:14 +0100
use yardoc for documentation
Diffstat:
M .gitignore | 1 +
A README.md | 5 +++++
D README.rdoc | 4 ----
M Rakefile | 14 +++++++-------
M generators/reports_as_sparkline_mi… | 2 +-
M lib/saulabs/reportable.rb | 43 +++++++++++++++++++----------…
M lib/saulabs/reportable/cumulated_r… | 19 ++++++++-----------
M lib/saulabs/reportable/grouping.rb | 33 +++++++++++++++++++++++++++--…
M lib/saulabs/reportable/report.rb | 90 +++++++++++++++++++++++------…
M lib/saulabs/reportable/report_cach… | 56 ++++++++++++++++++++++-----…
M lib/saulabs/reportable/reporting_p… | 94 +++++++++++++++++++++++++++…
M lib/saulabs/reportable/sparkline_t… | 39 ++++++++++++++++++++-------…
12 files changed, 296 insertions(+), 104 deletions(-)
---
diff --git a/.gitignore b/.gitignore
@@ -2,3 +2,4 @@
spec/log/spec.log
spec/db/reportable.sqlite3.db
doc
+.yardoc
diff --git a/README.md b/README.md
@@ -0,0 +1,4 @@
+Reportable
+----------
+
+Former ReportsAsSparkline; expect new features, cleaner code etc. in the next …
+\ No newline at end of file
diff --git a/README.rdoc b/README.rdoc
@@ -1,3 +0,0 @@
-= Reportable
-
-Former ReportsAsSparkline; expect new features, cleaner code etc. in the next …
-\ No newline at end of file
diff --git a/Rakefile b/Rakefile
@@ -22,13 +22,13 @@ Spec::Rake::SpecTask.new(:spec) do |t|
t.spec_files = FileList['spec/**/*_spec.rb']
end
-desc 'Generate documentation for the ReportsAsSparkline plugin.'
-Rake::RDocTask.new(:rdoc) do |rdoc|
- rdoc.rdoc_dir = 'doc'
- rdoc.title = 'ReportsAsSparkline'
- rdoc.options << '--line-numbers' << '--inline-source'
- rdoc.rdoc_files.include('README.rdoc')
- rdoc.rdoc_files.include('lib/**/*.rb')
+begin
+ require 'yard'
+ YARD::Rake::YardocTask.new(:doc) do |t|
+ t.files = ['lib/**/*.rb', '-', 'README.md']
+ t.options = ['--no-private', '--title', 'Reportable Documentation']
+ end
+rescue LoadError
end
begin
diff --git a/generators/reports_as_sparkline_migration/reports_as_sparkline_mig…
@@ -1,4 +1,4 @@
-class ReportableMigrationGenerator < Rails::Generator::NamedBase #:nodoc:
+class ReportableMigrationGenerator < Rails::Generator::NamedBase
def manifest
record do |m|
diff --git a/lib/saulabs/reportable.rb b/lib/saulabs/reportable.rb
@@ -1,31 +1,40 @@
-module Saulabs #:nodoc:
+module Saulabs
module Reportable
- def self.included(base) #:nodoc:
+ # Includes the {Saulabs::Reportable.reportable} method into +base+.
+ #
+ def self.included(base)
base.extend ClassMethods
end
module ClassMethods
- # Generates a report on a model. That report can then be executed via th…
+ # Generates a report on a model. That report can then be executed via th…
#
- # ==== Parameters
+ # @param [String] name
+ # the name of the report, also defines the name of the generated repor…
+ # @param [Hash] options
+ # the options to generate the reports with
#
- # * <tt>name</tt> - The name of the report, defines the name of the gene…
+ # @option options [Symbol] :date_column (created_at)
+ # the name of the date column over that the records are aggregated
+ # @option options [String, Symbol] :value_column (:id)
+ # the name of the column that holds the values to aggregate when using…
+ # @option options [Symbol] :aggregation (:count)
+ # the aggregation to use (one of +:count+, +:sum+, +:minimum+, +:maxim…
+ # @option options [Symbol] :grouping (:day)
+ # the period records are grouped in (+:hour+, +:day+, +:week+, +:month…
+ # @option options [Fixnum] :limit (100)
+ # the number of reporting periods to get (see +:grouping+)
+ # @option options [Hash] :conditions ({})
+ # conditions like in +ActiveRecord::Base#find+; only records that matc…
+ # @option options [Boolean] :live_data (false)
+ # specifies whether data for the current reporting period is to be rea…
+ # @option options [DateTime, Boolean] :end_date (false)
+ # when specified, the report will only include data for the +:limit+ r…
#
- # ==== Options
- #
- # * <tt>:date_column</tt> - The name of the date column over that the re…
- # * <tt>:value_column</tt> - The name of the column that holds the value…
- # * <tt>:aggregation</tt> - The aggregation to use (one of <tt>:count</t…
- # * <tt>:grouping</tt> - The period records are grouped on (<tt>:hour</t…
- # * <tt>:limit</tt> - The number of reporting periods to get (see <tt>:g…
- # * <tt>:conditions</tt> - Conditions like in <tt>ActiveRecord::Base#fin…
- # * <tt>:live_data</tt> - Specifies whether data for the current reporti…
- # * <tt>:end_date</tt> - When specified, the report will only include da…
- #
- # ==== Examples
+ # @example Declaring reports on a model
#
# class User < ActiveRecord::Base
# reportable :registrations, :aggregation => :count
diff --git a/lib/saulabs/reportable/cumulated_report.rb b/lib/saulabs/reportabl…
@@ -1,26 +1,23 @@
-module Saulabs #:nodoc:
+module Saulabs
- module Reportable #:nodoc:
+ module Reportable
- # A special report class that cumulates all data (see Saulabs::Reportable:…
+ # A special report class that cumulates all data (see {Saulabs::Reportable…
#
- # ==== Examples
- #
- # When Saulabs::Reportable::Report returns
+ # @example Cumulated reports as opposed to regular reports
#
# [[<DateTime today>, 1], [<DateTime yesterday>, 2], etc.]
- #
- # Saulabs::Reportable::CumulatedReport returns
- #
# [[<DateTime today>, 3], [<DateTime yesterday>, 2], etc.]
+ #
class CumulatedReport < Report
- # Runs the report (see Saulabs::Reportable::Report#run)
+ # Runs the report (see {Saulabs::Reportable::Report#run})
+ #
def run(options = {})
cumulate(super, options_for_run(options))
end
- protected
+ private
def cumulate(data, options)
first_reporting_period = ReportingPeriod.first(options[:grouping], o…
diff --git a/lib/saulabs/reportable/grouping.rb b/lib/saulabs/reportable/groupi…
@@ -1,18 +1,38 @@
-module Saulabs #:nodoc:
+module Saulabs
- module Reportable #:nodoc:
+ module Reportable
- class Grouping #:nodoc:
+ # The grouping specifies which records are grouped into one {Saulabs::Repo…
+ #
+ class Grouping
+ # Initializes a new grouping.
+ #
+ # @param [Symbol] identifier
+ # the identifier of the grouping (one of +:hour+, +:day+, +:week+ or +…
+ #
def initialize(identifier)
raise ArgumentError.new("Invalid grouping #{identifier}") unless [:hou…
@identifier = identifier
end
+ # Gets the identifier of the grouping.
+ #
+ # @returns [Symbol]
+ # the identifier of the grouping.
+ #
def identifier
@identifier
end
+ # Gets an array of date parts from a DB string.
+ #
+ # @param [String] db_string
+ # the DB string to get the date parts from
+ #
+ # @returns [Array<Fixnum>]
+ # array of numbers that represent the values of the date
+ #
def date_parts_from_db_string(db_string)
case ActiveRecord::Base.connection.adapter_name
when /mysql/i
@@ -24,7 +44,12 @@ module Saulabs #:nodoc:
end
end
- def to_sql(date_column) #:nodoc:
+ # Converts the grouping into a DB specific string that can be used to gr…
+ #
+ # @param [String] date_column
+ # the name of the DB column that holds the date
+ #
+ def to_sql(date_column)
case ActiveRecord::Base.connection.adapter_name
when /mysql/i
mysql_format(date_column)
diff --git a/lib/saulabs/reportable/report.rb b/lib/saulabs/reportable/report.rb
@@ -1,26 +1,61 @@
-module Saulabs #:nodoc:
+module Saulabs
- module Reportable #:nodoc:
+ module Reportable
- # The Report class that does all the data retrieval and calculations
+ # The Report class that does all the data retrieval and calculations.
+ #
class Report
- attr_reader :klass, :name, :date_column, :value_column, :aggregation, :o…
+ # the model the report works on (This is the class you invoke {Saulabs::…
+ #
+ attr_reader :klass
+
+ # the name of the report (as in {Saulabs::Reportable::ClassMethods#repor…
+ #
+ attr_reader :name
+
+ # the name of the date column over that the records are aggregated
+ #
+ attr_reader :date_column
+
+ # the name of the column that holds the values to aggregate when using a…
+ #
+ attr_reader :value_column
- # ==== Parameters
- # * <tt>klass</tt> - The model the report works on (This is the class yo…
- # * <tt>name</tt> - The name of the report (as in Saulabs::Reportable::C…
+ # the aggregation to use (one of +:count+, +:sum+, +:minimum+, +:maximum…
#
- # ==== Options
+ attr_reader :aggregation
+
+ # options for the report
+ #
+ attr_reader :options
+
+ # Initializes a new {Saulabs::Reportable::Report}
+ #
+ # @param [Class] klass
+ # the model the report works on (This is the class you invoke {Saulabs…
+ # @param [String] name
+ # the name of the report (as in {Saulabs::Reportable::ClassMethods#rep…
+ # @param [Hash] options
+ # options for the report creation
+ #
+ # @option options [Symbol] :date_column (created_at)
+ # the name of the date column over that the records are aggregated
+ # @option options [String, Symbol] :value_column (:id)
+ # the name of the column that holds the values to aggregate when using…
+ # @option options [Symbol] :aggregation (:count)
+ # the aggregation to use (one of +:count+, +:sum+, +:minimum+, +:maxim…
+ # @option options [Symbol] :grouping (:day)
+ # the period records are grouped in (+:hour+, +:day+, +:week+, +:month…
+ # @option options [Fixnum] :limit (100)
+ # the number of reporting periods to get (see +:grouping+)
+ # @option options [Hash] :conditions ({})
+ # conditions like in +ActiveRecord::Base#find+; only records that matc…
+ # @option options [Boolean] :live_data (false)
+ # specifies whether data for the current reporting period is to be rea…
+ # @option options [DateTime, Boolean] :end_date (false)
+ # when specified, the report will only include data for the +:limit+ r…
#
- # * <tt>:date_column</tt> - The name of the date column over that the re…
- # * <tt>:value_column</tt> - The name of the column that holds the value…
- # * <tt>:aggregation</tt> - The aggregation to use (one of <tt>:count</t…
- # * <tt>:grouping</tt> - The period records are grouped on (<tt>:hour</t…
- # * <tt>:limit</tt> - The number of reporting periods to get (see <tt>:g…
- # * <tt>:conditions</tt> - Conditions like in <tt>ActiveRecord::Base#fin…
- # * <tt>:live_data</tt> - Specifies whether data for the current reporti…
- # * <tt>:end_date</tt> - When specified, the report will only include da…
def initialize(klass, name, options = {})
ensure_valid_options(options)
@klass = klass
@@ -41,12 +76,23 @@ module Saulabs #:nodoc:
# Runs the report and returns an array of array of DateTimes and Floats
#
- # ==== Options
- # * <tt>:grouping</tt> - The period records are grouped on (<tt>:hour</t…
- # * <tt>:limit</tt> - The number of reporting periods to get (see <tt>:g…
- # * <tt>:conditions</tt> - Conditions like in <tt>ActiveRecord::Base#fin…
- # * <tt>:live_data</tt> - Specifies whether data for the current reporti…
- # * <tt>:end_date</tt> - When specified, the report will only include da…
+ # @param [Hash] options
+ # options to run the report with
+ #
+ # @option options [Symbol] :grouping (:day)
+ # the period records are grouped in (+:hour+, +:day+, +:week+, +:month…
+ # @option options [Fixnum] :limit (100)
+ # the number of reporting periods to get (see +:grouping+)
+ # @option options [Hash] :conditions ({})
+ # conditions like in +ActiveRecord::Base#find+; only records that matc…
+ # @option options [Boolean] :live_data (false)
+ # specifies whether data for the current reporting period is to be rea…
+ # @option options [DateTime, Boolean] :end_date (false)
+ # when specified, the report will only include data for the +:limit+ r…
+ #
+ # @returns [Array<Array<DateTime, Float>>]
+ # the result of the report as pairs of {DateTime}s and {Float}s
+ #
def run(options = {})
options = options_for_run(options)
ReportCache.process(self, options) do |begin_at, end_at|
diff --git a/lib/saulabs/reportable/report_cache.rb b/lib/saulabs/reportable/re…
@@ -1,9 +1,10 @@
-module Saulabs #:nodoc:
+module Saulabs
- module Reportable #:nodoc:
+ module Reportable
- # The ReportCache class is a regular +ActiveRecord+ model and represents c…
- # ReportCache instances are identified by the combination of +model_name+,…
+ # The +ReportCache+ class is a regular {ActiveRecord} model and represents…
+ # +ReportCache+ instances are identified by the combination of +model_name…
+ #
class ReportCache < ActiveRecord::Base
set_table_name :reportable_cache
@@ -12,17 +13,19 @@ module Saulabs #:nodoc:
# Clears the cache for the specified +klass+ and +report+
#
- # === Parameters
- # * <tt>klass</tt> - The model the report to clear the cache for works on
- # * <tt>report</tt> - The name of the report to clear the cache for
+ # @param [Class] klass
+ # the model the report to clear the cache for works on
+ # @param [Symbol] report
+ # the name of the report to clear the cache for
+ #
+ # @example Clearing the cache for a report
+ #
+ # class User < ActiveRecord::Base
+ # reportable :registrations
+ # end
+ #
+ # Saulabs::Reportable::ReportCache.clear_for(User, :registrations)
#
- # === Example
- # To clear the cache for a report defined as
- # class User < ActiveRecord::Base
- # reportable :registrations
- # end
- # just do
- # Saulabs::Reportable::ReportCache.clear_for(User, :registrations)
def self.clear_for(klass, report)
self.delete_all(:conditions => {
:model_name => klass.name,
@@ -30,7 +33,28 @@ module Saulabs #:nodoc:
})
end
- def self.process(report, options, &block) #:nodoc:
+ # Processes the report using the respective cache.
+ #
+ # @param [Saulabe::Reportable::Report] report
+ # the report to process
+ # @param [Hash] options
+ # options for the report
+ #
+ # @option options [Symbol] :grouping (:day)
+ # the period records are grouped in (+:hour+, +:day+, +:week+, +:month…
+ # @option options [Fixnum] :limit (100)
+ # the number of reporting periods to get (see +:grouping+)
+ # @option options [Hash] :conditions ({})
+ # conditions like in +ActiveRecord::Base#find+; only records that matc…
+ # @option options [Boolean] :live_data (false)
+ # specifies whether data for the current reporting period is to be rea…
+ # @option options [DateTime, Boolean] :end_date (false)
+ # when specified, the report will only include data for the +:limit+ r…
+ #
+ # @returns [Array<Array<DateTime, Float>>]
+ # the result of the report as pairs of {DateTime}s and {Float}s
+ #
+ def self.process(report, options, &block)
raise ArgumentError.new('A block must be given') unless block_given?
self.transaction do
cached_data = read_cached_data(report, options)
@@ -44,7 +68,7 @@ module Saulabs #:nodoc:
def self.prepare_result(new_data, cached_data, report, options)
new_data = new_data.map { |data| [ReportingPeriod.from_db_string(opt…
cached_data.map! { |cached| [ReportingPeriod.new(options[:grouping],…
- current_reporting_period = ReportingPeriod.current(options[:grouping…
+ current_reporting_period = ReportingPeriod.new(options[:grouping])
reporting_period = get_first_reporting_period(options)
result = []
while reporting_period < (options[:end_date] ? ReportingPeriod.new(o…
diff --git a/lib/saulabs/reportable/reporting_period.rb b/lib/saulabs/reportabl…
@@ -1,28 +1,74 @@
-module Saulabs #:nodoc:
+module Saulabs
- module Reportable #:nodoc:
+ module Reportable
- class ReportingPeriod #:nodoc:
+ # A reporting period is a specific hour or a specific day etc. depending o…
+ #
+ class ReportingPeriod
- attr_reader :date_time, :grouping
+ # The actual {DateTime} the reporting period represents
+ #
+ attr_reader :date_time
+ # The {Saulabs::Reportable::Grouping} of the reporting period
+ #
+ attr_reader :grouping
+
+ # Initializes a new reporting period.
+ #
+ # @param [Saulabs::Reportable::Grouping] grouping
+ # the grouping the generate the reporting period for
+ # @param [DateTime] date_time
+ # the {DateTime} to generate the reporting period for
+ #
def initialize(grouping, date_time = nil)
@grouping = grouping
@date_time = parse_date_time(date_time || DateTime.now)
end
+ # Gets a reporting period relative to the current one.
+ #
+ # @param [Fixnum] offset
+ # the offset to get the reporting period for
+ #
+ # @returns [Saulabs::Reportable::ReportingPeriod]
+ # the reporting period relative by offset to the current one
+ #
+ # @example Getting the reporting period one week later
+ #
+ # reporting_period = Saulabs::Reportable::ReportingPeriod.new(:week, D…
+ # next_week = reporting_period.offset(1)
+ #
def offset(offset)
self.class.new(@grouping, @date_time + offset.send(@grouping.identifie…
end
+ # Gets the first reporting period for a grouping and a limit (optionally…
+ #
+ # @param [Saulabs::ReportingPeriod::Grouping] grouping
+ # the grouping to get the first reporting period for
+ # @param [Fixnum] limit
+ # the limit to get the first reporting period for
+ # @param [DateTime] end_date
+ # the end date to get the first reporting period for (the first report…
+ #
+ # @returns [Saulabs::Reportable::ReportingPeriod]
+ # the first reporting period for the grouping, limit and optionally en…
+ #
def self.first(grouping, limit, end_date = nil)
self.new(grouping, end_date).offset(-limit)
end
- def self.current(grouping)
- self.new(grouping, Time.now)
- end
-
+ # Gets a reporting period from a DB date string.
+ #
+ # @param [Saulabs::Reportable::Grouping] grouping
+ # the grouping to get the reporting period for
+ # @param [String] db_string
+ # the DB string to parse and get the reporting period for
+ #
+ # @returns [Saulabs::Reportable::ReportingPeriod]
+ # the reporting period for the {Saulabs::Reportable::Grouping} as pars…
+ #
def self.from_db_string(grouping, db_string)
parts = grouping.date_parts_from_db_string(db_string)
result = case grouping.identifier
@@ -38,14 +84,32 @@ module Saulabs #:nodoc:
result
end
+ # Gets the next reporting period.
+ #
+ # @returns [Saulabs::Reportable::ReportingPeriod]
+ # the reporting period after the current one
+ #
def next
self.offset(1)
end
+ # Gets the previous reporting period.
+ #
+ # @returns [Saulabs::Reportable::ReportingPeriod]
+ # the reporting period before the current one
+ #
def previous
self.offset(-1)
end
+ # Gets whether the reporting period +other+ is equal to the current one.
+ #
+ # @param [Saulabs::Reportable::ReportingPeriod] other
+ # the reporting period to check for whether it is equal to the current…
+ #
+ # @returns [Boolean]
+ # true if +other+ is equal to the current reporting period, false othe…
+ #
def ==(other)
if other.is_a?(Saulabs::Reportable::ReportingPeriod)
@date_time.to_s == other.date_time.to_s && @grouping.identifier.to_s…
@@ -56,6 +120,14 @@ module Saulabs #:nodoc:
end
end
+ # Gets whether the reporting period +other+ is smaller to the current on…
+ #
+ # @param [Saulabs::Reportable::ReportingPeriod] other
+ # the reporting period to check for whether it is smaller to the curre…
+ #
+ # @returns [Boolean]
+ # true if +other+ is smaller to the current reporting period, false ot…
+ #
def <(other)
if other.is_a?(Saulabs::Reportable::ReportingPeriod)
return @date_time < other.date_time
@@ -66,6 +138,12 @@ module Saulabs #:nodoc:
end
end
+ # Gets the latest point in time that is included the reporting period. T…
+ # for grouping hour would be that hour and 59 minutes and 59 seconds.
+ #
+ # @returns [DateTime]
+ # the latest point in time that is included in the reporting period
+ #
def last_date_time
case @grouping.identifier
when :hour
diff --git a/lib/saulabs/reportable/sparkline_tag_helper.rb b/lib/saulabs/repor…
@@ -1,27 +1,38 @@
-module Saulabs #:nodoc:
+module Saulabs
- module Reportable #:nodoc:
+ module Reportable
module SparklineTagHelper
# Renders a sparkline with the given data.
#
- # ==== Parameters
+ # @param [Array<Array<DateTime, Float>>] data
+ # an array of report data as returned by {Saulabs::Reportable::Report#…
+ # @param [Hash] options
+ # options for the sparkline
#
- # * <tt>data</tt> - The data to render the sparkline for, is retrieved f…
+ # @option options [Fixnum] :width (300)
+ # the width of the generated image
+ # @option options [Fixnum] :height (34)
+ # the height of the generated image
+ # @option options [String] :line_color ('0077cc')
+ # the line color of the generated image
+ # @option options [String] :fill_color ('e6f2fa')
+ # the fill color of the generated image
+ # @option options [Array<Symbol>] :labels ([])
+ # the axes to render lables for (Array of +:x+, +:y+, +:r+, +:t+; this…
+ # @option options [String] :alt ('')
+ # the alt attribute for the generated image
+ # @option options [String] :title ('')
+ # the title attribute for the generated image
#
- # ==== Options
+ # @returns [String]
+ # an image tag showing a sparkline for the passed +data+
#
- # * <tt>width</tt> - The width of the generated image
- # * <tt>height</tt> - The height of the generated image
- # * <tt>line_color</tt> - The line color of the sparkline (hex code)
- # * <tt>fill_color</tt> - The color to fill the area below the sparkline…
- # * <tt>labels</tt> - The axes to render lables for (Array of <tt>:x</tt…
- # * <tt>alt</tt> - The HTML img alt tag
- # * <tt>title</tt> - The HTML img title tag
+ # @example Rendering a sparkline tag for report data
+ #
+ # <%= sparkline_tag(User.registrations_report, :width => 200, :height …
#
- # ==== Example
- # <tt><%= sparkline_tag(User.registrations_report, :width => 200, :heigh…
def sparkline_tag(data, options = {})
options.reverse_merge!({ :width => 300, :height => 34, :line_color => …
data = data.collect { |d| d[1] }
You are viewing proxied material from jay.scot. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.