Class: RVGP::Base::Grid

Inherits:
Object
  • Object
show all
Extended by:
Pta::AvailabilityHelper, Utilities
Includes:
Application::DescendantRegistry, Pta::AvailabilityHelper, Utilities
Defined in:
lib/rvgp/base/grid.rb

Overview

This is the base class implementation, for your application-defined grids. This class offers the bulk of functionality that your grids will use. The goal of a grid, is to compute csv files, in the project’s build/grids directory. Sometimes, these grids will simply be an assemblage of pta queries. Other times, these grids won’t involve any pta queries at all, and may instead contain projections and statistics computed elsewhere.

Users are expected to inherit from this class, in their grid bulding implementations, inside ruby classes defined in your project’s app/grids directory. This class offers helpers for working with pta_adapters (particularly for use with by-month queries). Additionally, this class offers code to detect and produce annual, and otherwise arbitary(see HasMultipleSheets) segmentation of grids.

The function and purpose of grids, in your project, is as follows:

  • Store a state of our data in the project’s build, and thus its git history.

  • Provide the data used by a subsequent Plot.

  • Provide the data used by a subsequent Utilities::GridQuery.

Each instance of Grid, in your build is expected to represent a segment of the data. Typically this segment will be as simple as a date range (either a specific year, or ‘all dates’). However, the included HasMultipleSheets module, allows you to add additional arbitrary segments (perhaps a segment for each value of a tag), that may be used to produce additional grids in your build, on top of the dated segments.

## Example Perhaps the easiest way to understand what this class does, is to look at one of the sample grids produced by the new_project command. Here’s the contents of an app/grids/wealth_growth_grid.rb, that you can use in your projects:

class WealthGrowthGrid < RVGP::Base::Grid
  grid 'wealth_growth', 'Generate Wealth Growth Grids', 'Wealth Growth by month (%s)',
       output_path_template: '%s-wealth-growth'

  def sheet_header
    %w[Date Assets Liabilities]
  end

  def sheet_body
    assets, liabilities = *%w[Assets Liabilities].map { |acct| monthly_totals acct, accrue_before_begin: true }

    months_through(starting_at, ending_at).map do |month|
      [month.strftime('%m-%y'), assets[month], liabilities[month]]
    end
  end
end

This WealthGrowthGrid, depending on your data, will output a series of grids in your build directory, such as the following:

  •  build/grids/2018-wealth-growth.csv

  •  build/grids/2019-wealth-growth.csv

  •  build/grids/2020-wealth-growth.csv

  •  build/grids/2021-wealth-growth.csv

  •  build/grids/2022-wealth-growth.csv

  •  build/grids/2023-wealth-growth.csv

And, inside each of this files, will be a csv similar to: “‘ Date,Assets,Liabilities 01-23,89418.01,-4357.45 02-23,89708.53,-3731.10 03-23,89899.81,-3150.35 04-23,89991.36,-2616.21 05-23,89982.94,-2129.60 06-23,89874.60,-1691.37 07-23,89666.59,-1302.28 08-23,89359.43,-963.00 09-23,88953.92,-674.13 10-23,88451.01,-436.16 “`

Defined Under Namespace

Modules: HasMultipleSheets

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Pta::AvailabilityHelper

hledger, ledger, pta

Methods included from Utilities

months_through, string_to_regex

Constructor Details

#initialize(starting_at, ending_at) ⇒ Grid

Create a Grid, given the following date segment

Parameters:



101
102
103
104
105
106
107
108
# File 'lib/rvgp/base/grid.rb', line 101

def initialize(starting_at, ending_at)
  # NOTE: It seems that with monthly queries, the ending date works a bit
  # differently. It's not necessariy to add one to the day here. If you do,
  # you get the whole month of January, in the next year added to the output.
  @year = starting_at.year
  @starting_at = starting_at
  @ending_at = ending_at
end

Class Attribute Details

.descriptionObject (readonly)

Returns the value of attribute description.



318
319
320
# File 'lib/rvgp/base/grid.rb', line 318

def description
  @description
end

.nameObject (readonly)

Returns the value of attribute name.



318
319
320
# File 'lib/rvgp/base/grid.rb', line 318

def name
  @name
end

.output_path_templateObject (readonly)

Returns the value of attribute output_path_template.



318
319
320
# File 'lib/rvgp/base/grid.rb', line 318

def output_path_template
  @output_path_template
end

Instance Attribute Details

#ending_atDate (readonly)

The last day in this instance of the grid

Returns:

  • (Date)

    the current value of ending_at



81
82
83
# File 'lib/rvgp/base/grid.rb', line 81

def ending_at
  @ending_at
end

#starting_atDate (readonly)

The first day in this instance of the grid

Returns:

  • (Date)

    the current value of starting_at



81
82
83
# File 'lib/rvgp/base/grid.rb', line 81

def starting_at
  @starting_at
end

#yearInteger (readonly)

The year segmentation, for an instance of this Grid. This value is pulled from the year of :ending_at.

Returns:

  • (Integer)

    the current value of year



81
82
83
# File 'lib/rvgp/base/grid.rb', line 81

def year
  @year
end

Class Method Details

.dependency_pathsArray<String>

This method returns an array of paths, to the files it produces it’s output from. This is used by rake to establish the freshness of our output. We assume that output is deterministic, and based on these inputs.

Returns:

  • (Array<String>)

    an array of relative paths, to our inputs.



341
342
343
344
345
346
347
# File 'lib/rvgp/base/grid.rb', line 341

def dependency_paths
  # NOTE: This is only used right now, in the plot task. So, the cache is fine.
  # But, if we start using this before the journals are built, we're going to
  # need to clear this cache, thereafter. So, maybe we want to take a parameter
  # here, or figure something out then, to prevent problems.
  @dependency_paths ||= pta.files(file: RVGP.app.config.project_journal_path)
end

.grid(name, description, status_name_template, options = {}) ⇒ void

This method returns an undefined value.

This helper method is provided for child classes, to easily establish a definition of this grid, that can be used to produce it’s instances, and their resulting output.

Parameters:

  • name (String)

    See name.

  • description (String)
  • status_name_template (String)

    A template to use, when composing the build status. A single ‘%s’ formatter is expected, which, will be substituted with the year of a segment or the string ‘all’.

  • options (String) (defaults to: {})

    what options to configure this registry with

Options Hash (options):



330
331
332
333
334
335
# File 'lib/rvgp/base/grid.rb', line 330

def grid(name, description, status_name_template, options = {})
  @name = name
  @description = description
  @status_name_template = status_name_template
  @output_path_template = options[:output_path_template]
end

.output_path(year) ⇒ String

Given a year, compute the output path for an instance of this grid

Parameters:

  • year (String, Integer)

    The year to which this output is specific. Or, alternatively ‘all’.

Returns:

  • (String)

    relative path to an output file

Raises:

  • (StandardError)


358
359
360
361
362
# File 'lib/rvgp/base/grid.rb', line 358

def output_path(year)
  raise StandardError, 'Missing output_path_template' unless output_path_template

  [RVGP.app.config.build_path('grids'), '/', output_path_template % year, '.csv'].join
end

.status_name(year) ⇒ String

Given a year, compute the status label for an instance of this grid

Parameters:

  • year (String, Integer)

    The year to which this status is specific. Or, alternatively ‘all’.

Returns:

  • (String)

    A friendly label, constructed from the :status_name_template



367
368
369
# File 'lib/rvgp/base/grid.rb', line 367

def status_name(year)
  @status_name_template % year
end

.uptodate?(year) ⇒ TrueClass, FalseClass

Whether this grid’s outputs are fresh. This is determined, by examing the mtime’s of our #dependency_paths.

Returns:

  • (TrueClass, FalseClass)

    true, if we’re fresh, false if we’re stale.



351
352
353
# File 'lib/rvgp/base/grid.rb', line 351

def uptodate?(year)
  FileUtils.uptodate? output_path(year), dependency_paths
end

Instance Method Details

#monthly_amounts(*args) ⇒ Hash<Date,RVGP::Journal::Commodity>

The provided args are passed to Pta::AvailabilityHelper#pta‘s #register. The amounts returned by this query are reduced by month. This means that the return value is a Hash, indexed by month (in the form of a Date class) whose value is itself a Commodity, which indicates the amount for that month.

In addition to the options supported by pta.register, the following options are supported:

  • accrue_before_begin [Boolean] - This flag will create a pta-adapter independent query, to accrue balances before the start date of the returned set. This is useful if you want to (say) output the current year’s amount’s, but, you want to start with the ending balance of the prior year, as opposed to ‘0’.

  • initial [Hash] - defaults to ({}). This is the value we begin to map values from. Typically we want to start that process from nil, this allows us to decorate the starting point.

  • in_code [String] - defaults to (‘$’) . This value, expected to be a commodity code, is ultimately passed to Pta::RegisterPosting#amount_in

Parameters:

Returns:



203
204
205
# File 'lib/rvgp/base/grid.rb', line 203

def monthly_amounts(*args)
  reduce_monthly(*args, :amount_in)
end

#monthly_amounts_by_account(*args) ⇒ Hash<String,Hash<Date,RVGP::Journal::Commodity>>

The provided args are passed to Pta::AvailabilityHelper#pta‘s #register. The amounts returned by this query are reduced by account, then month. This means that the return value is a Hash, whose keys correspond to each of the accounts that were encounted. The values for each of those keys, is itself a Hash indexed by month, whose value is the amount amount returned, for that month.

In addition to the options supported by pta.register, the following options are supported:

  • accrue_before_begin [Boolean] - This flag will create a pta-adapter independent query, to accrue balances before the start date of the returned set. This is useful if you want to (say) output the current year’s amount’s, but, you want to start with the ending balance of the prior year, as opposed to ‘0’.

  • initial [Hash] - defaults to ({}). This is the value we begin to map values from. Typically we want to start that process from nil, this allows us to decorate the starting point.

  • in_code [String] - defaults to (‘$’) . This value, expected to be a commodity code, is ultimately passed to Pta::RegisterPosting#amount_in

Parameters:

Returns:



163
164
165
# File 'lib/rvgp/base/grid.rb', line 163

def (*args)
  (*args, :amount_in)
end

#monthly_totals(*args) ⇒ Hash<Date,RVGP::Journal::Commodity>

The provided args are passed to Pta::AvailabilityHelper#pta‘s #register. The total amounts returned by this query are reduced by month. This means that the return value is a Hash, indexed by month (in the form of a Date class) whose value is itself a Commodity, which indicates the total for that month.

In addition to the options supported by pta.register, the following options are supported:

  • accrue_before_begin [Boolean] - This flag will create a pta-adapter independent query, to accrue balances before the start date of the returned set. This is useful if you want to (say) output the current year’s amount’s, but, you want to start with the ending balance of the prior year, as opposed to ‘0’.

  • initial [Hash] - defaults to ({}). This is the value we begin to map values from. Typically we want to start that process from nil, this allows us to decorate the starting point.

  • in_code [String] - defaults to (‘$’) . This value, expected to be a commodity code, is ultimately passed to Pta::RegisterPosting#total_in

Parameters:

Returns:



183
184
185
# File 'lib/rvgp/base/grid.rb', line 183

def monthly_totals(*args)
  reduce_monthly(*args, :total_in)
end

#monthly_totals_by_account(*args) ⇒ Hash<String,Hash<Date,RVGP::Journal::Commodity>>

The provided args are passed to Pta::AvailabilityHelper#pta‘s ’#register. The total amounts returned by this query are reduced by account, then month. This means that the return value is a Hash, whose keys correspond to each of the accounts that were encounted. The values for each of those keys, is itself a Hash indexed by month, whose value is the total amount returned, for that month.

In addition to the options supported by pta.register, the following options are supported:

  • accrue_before_begin [Boolean] - This flag will create a pta-adapter independent query, to accrue balances before the start date of the returned set. This is useful if you want to (say) output the current year’s total’s, but, you want to start with the ending balance of the prior year, as opposed to ‘0’.

  • initial [Hash] - defaults to ({}). This is the value we begin to map values from. Typically we want to start that process from nil, this allows us to decorate the starting point.

  • in_code [String] - defaults to (‘$’) . This value, expected to be a commodity code, is ultimately passed to Pta::RegisterPosting#total_in

Parameters:

Returns:



142
143
144
# File 'lib/rvgp/base/grid.rb', line 142

def (*args)
  (*args, :total_in)
end

#to_file!void

This method returns an undefined value.

Write the computed grid, to its default build path



112
113
114
115
# File 'lib/rvgp/base/grid.rb', line 112

def to_file!
  write! self.class.output_path(year), to_table
  nil
end

#to_tableArray[Array<String>]

Return the computed grid, in a parsed form, before it’s serialized to a string.

Returns:

  • (Array[Array<String>])

    Each row is an array, itself composed of an array of cells.



119
120
121
# File 'lib/rvgp/base/grid.rb', line 119

def to_table
  [sheet_header] + sheet_body
end