Extract class: RecordHistory

The methods `#index`, `.subsequent`, and `.preceding` contain
duplicated logic re: how to order, chronologically, a set of
versions, specifically a set representing the history of a single
record.

The extracted class only supports `#index` so far, but it should
be possilbe to use in `.subsequent` and `.preceding` also.
This commit is contained in:
Jared Beck 2015-11-02 00:15:23 -05:00
parent 8402e1be2b
commit a87dbfad0b
2 changed files with 64 additions and 8 deletions

View File

@ -0,0 +1,59 @@
module PaperTrail
# Represents the history of a single record.
# @api private
class RecordHistory
# @param versions - ActiveRecord::Relation - All versions of the record.
# @param version_class - Class - Usually PaperTrail::Version,
# but it could also be a custom version class.
# @api private
def initialize(versions, version_class)
@versions = versions
@version_class = version_class
end
# Returns ordinal position of `version` in `sequence`.
# @api private
def index(version)
sequence.index(version)
end
private
# Returns `@versions` in chronological order.
# @api private
def sequence
if @version_class.primary_key_is_int?
@versions.select(primary_key).order(primary_key.asc)
else
@versions.
select([timestamp, primary_key]).
order(@version_class.timestamp_sort_order)
end
end
# @return - Arel::Attribute - Attribute representing the primary key
# of the version table. The column's data type is usually a serial
# integer (the rails convention) but not always.
# @api private
def primary_key
table[@version_class.primary_key]
end
# @return - Arel::Table - The version table, usually named `versions`, but
# not always.
# @api private
def table
@version_class.arel_table
end
# @return - Arel::Attribute - Attribute representing the timestamp column
# of the version table, usually named `created_at` (the rails convention)
# but not always.
# @api private
def timestamp
table[PaperTrail.timestamp_field]
end
end
end

View File

@ -231,15 +231,12 @@ module PaperTrail
@previous ||= sibling_versions.preceding(self).first
end
# Returns an integer representing the chronological position of the
# version among its siblings (see `sibling_versions`). The "create" event,
# for example, has an index of 0.
# @api public
def index
table = self.class.arel_table unless @index
@index ||=
if self.class.primary_key_is_int?
sibling_versions.select(table[self.class.primary_key]).order(table[self.class.primary_key].asc).index(self)
else
sibling_versions.select([table[PaperTrail.timestamp_field], table[self.class.primary_key]]).
order(self.class.timestamp_sort_order).index(self)
end
@index ||= PaperTrail::RecordHistory.new(sibling_versions, self.class).index(self)
end
private