This library provides a simple algorithm for object filtering based on an object's timestamp. A master list of object ID's and timestamps are managed by this library and can be persisted (outside of this library) for picking up where you last left off.

filtering, ruby, timestamp, timestamp-filter
gem install fresh_objects -v 1.0.0


Fresh Objects

Gem Version Build Status Maintainability Test Coverage License: MIT

This library was built to support incoming data streams where you may or may not get the data in order. Since the data coming in is guaranteed to be complete "per object", you only need to keep the latest copy of it and discard stale versions. You can use this library to pass in all this data (in or out of order) and it will ensure only the freshest data is kept (stale copies are discarded.)

Note: persistence is outside of the scope of this library. You can, however, use this library to access the "object id => timestamp" hash structure that is used for filtering and persist it. Then, you can use it to re-hydrate a filter and pick up where you left off.


To install through Rubygems:

gem install install fresh_objects

You can also add this to your Gemfile:

bundle add fresh_objects


Say we have the following dataset:

objects = [
    id: 1,
    name: 'Clark Kent'
    timestamp: '2019-01-02 12:00:00 UTC'
    id: 1,
    name: 'Superman'
    timestamp: '2019-01-02 12:00:01 UTC'
    id: 1,
    name: 'John Doe'
    timestamp: '2019-01-02 11:59:59 UTC'

You could pass these objects into this library in order to resolve that the object you really want is the "Superman" object:

filter = FreshObjects.filter(timestamp_key: :timestamp).add_each(objects)

filtered_objects = filter.objects

Now, filtered_objects should equal:

    id: 1,
    name: 'Superman'
    timestamp: '2019-01-02 12:00:01 UTC'


  • You can change the object ID key by passing in the id_key into FreshObjects#filter.
  • You can change the timestamp key by passing in the timestamp_key into FreshObjects#filter.

The Resolver

A resolver is an object with a get method with the signature: get(object, expression) where object is the inputted object and expression is the key (or key-path of the value you want to retrieve.) By default, the Objectable is used. Objectable provides several benefits out-of-the-box since it:

  • supports nested objects (using key-path dot notation)
  • works with hashes and all other object types
  • works with attributes and methods

Chances are the default resolver works. In case you need to enhance or change the resolution implementation you are free to pass in your own customization of Objectable or swap it for a who new implementation altogether. See the Objectable repository for more information.

Saving a Filter

Ultimately what backs a filter is a hash with strings as keys and Time objects as values. This can be accessed for persistence:

lookup = filter.timestamps_by_id

Then, you can re-constitute a filter from this:

filter = FreshObjects.filter(lookup: timestamps_by_id)


  • The lookup is just the timestamp cache, it does not contain the other options such as other Filter#new options.
  • The next time you use a re-constituted filter, objects will be empty. That means the #objects method is not cumulative across uses (per object instance.) Remember, the goal of this library is the core filtering algorithm, not persistence.


Development Environment Configuration

Basic steps to take to get this repository compiling:

  1. Install Ruby (check fresh_objects.gemspec for versions supported)
  2. Install bundler (gem install bundler)
  3. Clone the repository (git clone
  4. Navigate to the root folder (cd fresh_objects)
  5. Install dependencies (bundle)

Running Tests

To execute the test suite and code-coverage tool, run:

bundle exec rspec spec --format documentation

Alternatively, you can have Guard watch for changes:

bundle exec guard

Also, do not forget to run Rubocop:

bundle exec rubocop

or run all three in one command:

bundle exec rake


Note: ensure you have proper authorization before trying to publish new versions.

After code changes have successfully gone through the Pull Request review process then the following steps should be followed for publishing new versions:

  1. Merge Pull Request into master
  2. Update lib/fresh_objects/version.rb using semantic versioning
  3. Install dependencies: bundle
  4. Update with release notes
  5. Commit & push master to remote and ensure CI builds master successfully
  6. Run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to

Code of Conduct

Everyone interacting in this codebase, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.


This project is MIT Licensed.