Class: Ruport::Data::Grouping
- Inherits:
-
Object
- Object
- Ruport::Data::Grouping
- Includes:
- Enumerable, Controller::Hooks
- Defined in:
- lib/ruport/data/grouping.rb
Overview
Overview
This class implements a grouping data structure for Ruport. A grouping is a collection of groups. It allows you to group the data in a table by one or more columns that you specify.
The data for a grouping is a hash of groups, keyed on each unique data point from the grouping column.
Instance Attribute Summary collapse
-
#data ⇒ Object
The grouping’s data.
-
#grouped_by ⇒ Object
readonly
The name of the column used to group the data.
Class Method Summary collapse
-
.inherited(base) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#<<(group) ⇒ Object
(also: #append)
Used to add extra data to the Grouping.
-
#[](name) ⇒ Object
Allows Hash-like indexing of the grouping data.
-
#each ⇒ Object
Iterates through the Grouping, yielding each group name and Group object.
-
#initialize(data = {}, options = {}) ⇒ Grouping
constructor
Creates a new Grouping based on the supplied options.
-
#initialize_copy(from) ⇒ Object
Create a copy of the Grouping.
-
#method_missing(id, *args) ⇒ Object
Provides a shortcut for the
as()
method by converting a call toto_format_name
into a call toas(:format_name)
. -
#sigma(column = nil) ⇒ Object
(also: #sum)
Calculates sums.
-
#sort_grouping_by(type = nil, &block) ⇒ Object
Returns a new grouping with the specified sort order.
-
#sort_grouping_by!(type = nil, &block) ⇒ Object
Applies the specified sort order to an existing Grouping object.
-
#subgrouping(name) ⇒ Object
(also: #/)
Provides access to the subgroups of a particular group in the Grouping.
-
#summary(field, procs) ⇒ Object
Useful for creating basic summaries from Grouping objects.
-
#to_s ⇒ Object
Uses Ruport’s built-in text formatter to render this Grouping.
Methods included from Controller::Hooks
Constructor Details
#initialize(data = {}, options = {}) ⇒ Grouping
Creates a new Grouping based on the supplied options.
Valid options:
:by
-
A column name or array of column names that the data will be grouped on.
:order
-
Determines the iteration and presentation order of a Grouping object. Set to :name to order by Group names. You can also provide a lambda which will be passed Group objects, and use semantics similar to Enumerable#group_by
Examples:
table = [[1,2,3],[4,5,6],[1,1,2]].to_table(%w[a b c])
# unordered
grouping = Grouping.new(table, :by => "a")
# ordered by group name
grouping = Grouping.new(table, :by => "a", :order => :name)
# ordered by group size
grouping = Grouping.new(table, :by => "a",
:order => lambda { |g| g.size } )
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/ruport/data/grouping.rb', line 164 def initialize(data={},={}) if data.kind_of?(Hash) @grouped_by = data[:by] @order = data[:order] @data = {} else @grouped_by = [:by] @order = [:order] cols = Array([:by]).dup @data = data.to_group.send(:grouped_data, cols.shift) cols.each do |col| @data.each do |_name,group| group.send(:create_subgroups, col) end end end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(id, *args) ⇒ Object
Provides a shortcut for the as()
method by converting a call to to_format_name
into a call to as(:format_name)
.
367 368 369 370 |
# File 'lib/ruport/data/grouping.rb', line 367 def method_missing(id,*args) return as($1.to_sym,*args) if id.to_s =~ /^to_(.*)/ super end |
Instance Attribute Details
#data ⇒ Object
The grouping’s data
183 184 185 |
# File 'lib/ruport/data/grouping.rb', line 183 def data @data end |
#grouped_by ⇒ Object (readonly)
The name of the column used to group the data
186 187 188 |
# File 'lib/ruport/data/grouping.rb', line 186 def grouped_by @grouped_by end |
Class Method Details
.inherited(base) ⇒ Object
:nodoc:
346 347 348 |
# File 'lib/ruport/data/grouping.rb', line 346 def self.inherited(base) #:nodoc: base.renders_as_grouping end |
Instance Method Details
#<<(group) ⇒ Object Also known as: append
245 246 247 248 249 250 |
# File 'lib/ruport/data/grouping.rb', line 245 def <<(group) if data.has_key? group.name raise(ArgumentError, "Group '#{group.name}' exists!") end @data.merge!({ group.name => group }) end |
#[](name) ⇒ Object
Allows Hash-like indexing of the grouping data.
Examples:
my_grouping["foo"]
194 195 196 197 |
# File 'lib/ruport/data/grouping.rb', line 194 def [](name) @data[name] or raise(IndexError,"Group Not Found") end |
#each ⇒ Object
Iterates through the Grouping, yielding each group name and Group object
201 202 203 204 205 206 207 208 209 |
# File 'lib/ruport/data/grouping.rb', line 201 def each if @order.respond_to?(:call) @data.sort_by { |_n,g| @order[g] }.each { |n,g| yield(n,g) } elsif @order == :name @data.sort_by { |n,_g| n }.each { |name,group| yield(name,group) } else @data.each { |name,group| yield(name,group) } end end |
#initialize_copy(from) ⇒ Object
359 360 361 362 |
# File 'lib/ruport/data/grouping.rb', line 359 def initialize_copy(from) #:nodoc: @grouped_by = from.grouped_by @data = from.data.inject({}) { |h,d| h.merge!({ d[0] => d[1].dup }) } end |
#sigma(column = nil) ⇒ Object Also known as: sum
Calculates sums. If a column name or index is given, it will try to convert each element of that column to an integer or float and add them together. The sum is calculated across all groups in the grouping.
If a block is given, it yields each Record in each Group so that you can do your own calculation.
Example:
table = [[1,2,3],[3,4,5],[5,6,7]].to_table(%w[col1 col2 col3])
grouping = Grouping(table, :by => "col1")
grouping.sigma("col2") #=> 12
grouping.sigma(0) #=> 12
grouping.sigma { |r| r.col2 + r.col3 } #=> 27
grouping.sigma { |r| r.col2 + 1 } #=> 15
329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/ruport/data/grouping.rb', line 329 def sigma(column=nil) inject(0) do |s, (_group_name, group)| if column s + group.sigma(column) else s + group.sigma do |r| yield(r) end end end end |
#sort_grouping_by(type = nil, &block) ⇒ Object
Returns a new grouping with the specified sort order. You can sort by Group name or an arbitrary block
by_name = grouping.sort_grouping_by(:name)
by_size = grouping.sort_grouping_by { |g| g.size }
217 218 219 220 221 |
# File 'lib/ruport/data/grouping.rb', line 217 def sort_grouping_by(type=nil,&block) a = Grouping.new(:by => @grouped_by, :order => type || block) each { |_n,g| a << g } return a end |
#sort_grouping_by!(type = nil, &block) ⇒ Object
Applies the specified sort order to an existing Grouping object.
grouping.sort_grouping_by!(:name)
grouping.sort_grouping_by! { |g| g.size }
227 228 229 |
# File 'lib/ruport/data/grouping.rb', line 227 def sort_grouping_by!(type=nil,&block) @order = type || block end |
#subgrouping(name) ⇒ Object Also known as: /
Provides access to the subgroups of a particular group in the Grouping. Supply the name of a group and it returns a Grouping created from the subgroups of the group.
258 259 260 261 262 |
# File 'lib/ruport/data/grouping.rb', line 258 def subgrouping(name) grouping = dup grouping.send(:data=, @data[name].subgroups) return grouping end |
#summary(field, procs) ⇒ Object
Useful for creating basic summaries from Grouping objects. Takes a field to summarize on, and then for each group, runs the specified procs and returns the results as a Table.
The following example would show for each date group, the sum for the attributes or methods :opened
and :closed
and order them by the :order
array.
If :order
is not specified, you cannot depend on predictable column order.
grouping.summary :date,
:opened => lambda { |g| g.sigma(:opened) },
:closed => lambda { |g| g.sigma(:closed) },
:order => [:date,:opened,:closed]
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/ruport/data/grouping.rb', line 282 def summary(field,procs) if procs[:order].kind_of?(Array) cols = procs.delete(:order) else cols = procs.keys + [field] end Table.new(:column_names => cols) { |t| each do |name,group| t << procs.inject({field => name}) do |s,r| s.merge(r[0] => r[1].call(group)) end end t.data.reorder(cols) } end |