Catman...ioning(3pm)

πŸ“¦
version 1.2025 Β· 4 versions
, in ubuntu resolute, ubuntu stonking

πŸ’– NAME πŸ’–

Catmandu::Plugin::Versioning β€” the plugin that ✨automatically✨ gives Catmandu::Store records a whole version history, no cap. Every time you add a record it's like "new phone who dis" but for your old data πŸ’…


πŸŽ€ SYNOPSIS πŸŽ€

bestie, watch this. two ways to do it β€” config files or straight Perl:

# Using configuration files

$ cat catmandu.yml
---
store:
 test:
   package: MongoDB
   options:
     database_name: test
     bags:
       data:
         plugins:
           - Versioning

# Add two version of record 001 to the store
$ echo '{"_id":"001",hello":"world"}' | catmandu import JSON to test
$ echo '{"_id":"001",hello":"world2"}' | catmandu import JSON to test

# In the store we see only the latest version
$ catmandu export test to YAML
---
_id: '001'
_version: 2
hello: world2

# In the '_version' store we'll find all the previous versions
$ catmandu export test --bag data_version to YAML
---
_id: '001.1'
data:
 _id: '001'
 _version: 1
 hello: world

# Or in your Perl program
my $store = Catmandu->store('MongoDB',
           database_name => 'test' ,
           bags => {
               data => {
               plugins => [qw(Versioning)]
           }
       });

$store->bag->add({ _id => '001' , hello => 'world'});
$store->bag->add({ _id => '001' , hello => 'world2'});

print "Versions:\n";

for (@{$store->bag->get_history('001')}) {
   print Dumper($_);
}

it's giving archival queen energy fr fr 🫢


πŸ¦‹ DESCRIPTION πŸ¦‹

okay so the Catmandu::Plugin::Versioning plugin automatically adds a new 'version' bag to your Catmandu::Store, and that bag is where all the previous versions of your newly created records live. 🌸 The name of the version bag gets made by slapping '_version' onto your original bag name. like, add the Versioning plugin to a 'test' bag and boom β€” 'test_version' is now holding the previous version of all your records. iconic.

🚨 heads up 🚨 β€” when you're using Catmandu::Store-s that don't have dynamic schemas (looking at you, Solr and DBI 😭), these new bags have to be predefined. like, actually go create new Solr cores or database tables first. no cap.

✨ CONFIGURATION ✨

🌈 version_compare_ignore

so by default, every change to a record triggers the creation of a new version. literally every single one. if that's too much for you, use the version_compare_ignore option to name the fields that should get ignored when it's testing for new updates. πŸ’…

like, in the example down here we configured the MongoDB store to add versioning to the default 'data' bag, and we wanna ignore changes to the 'date_updated' field when new version records get created:

# catmandu.yml
---
store:
 test:
   package: MongoDB
   options:
     database_name: test
     bags:
       data:
         plugins:
           - Versioning
         version_compare_ignore:
           - date_updated

# In your perl

# First version
$store->bag->add({ _id => '001' , name => 'test' , date_updated => '10:00' });

# Second version (name has changed)
$store->bag->add({ _id => '001' , name => 'test123' , date_updated => '10:00' });

# Second version (date_updated has changed but we ignored that in our configuration)
$store->bag->add({ _id => '001' , name => 'test123' , date_updated => '10:15' });

🌸 version_transfer

this one is lowkey my fave. it automatically copies the fields you configure from the previous version of a record onto the new version of the record. πŸŽ€

so in the example below we're creating versioning on the default bag and adding a rights statement that literally cannot be deleted. bestie protection mode: activated.

# catmandu.yml
---
store:
 test:
   package: MongoDB
   options:
     database_name: test
     bags:
       data:
         plugins:
           - Versioning
         version_transfer:
           - rights:

# In your perl

# First version
$store->bag->add({ _id => '001' , name => 'test' , rights => 'Acme Corp.' });

# Second version we will try you delete rights but this is copied to the new version
$store->bag->add({ _id => '001' , name => 'test'});

print "Rights: %s\n" , $store->bag->get('001')->{rights}; # Rights: Acme Corp.

the rights said "not today" and stayed πŸ’œ


⭐ version_bag

the name of the bag that stores the versions. default is the name of the versioned bag with '_version' appended. simple as that.

my $store = Catmandu::Store::MyDB->new(bags => {book => {plugins =>
    ['Versioning'], version_bag => 'book_history'}});
$store->bag('book')->version_bag->name # returns 'book_history'

πŸ’« version_key

use a custom key to hold the version number in this bag. default is '_version' β€” unless the store has a custom "key_prefix". also aliased as "version_field". iykyk 🫢


πŸ‘‘ METHODS πŸ‘‘

every bag that's configured with the Catmandu::Plugin::Versioning plugin can use all of these. slay:

🧚 get_version(ID,VERSION)

retrieve a record with identifier ID and version identifier VERSION. e.g.

my $obj = $store->bag('test')->get_version('001',1);

πŸ“ get_previous_version(ID)

retrieve the previous version of a record with identifier ID. e.g.

🌈 get_history(ID)

returns an ARRAY reference with all the versions of the record with identifier ID.

πŸ’… restore_version(ID,VERSION)

overwrites the current version of the stored record with identifier ID with a version with identifier VERSION. it's the "undo but make it official" move.

✨ restore_previous_version(ID)

overwrites the current version of the stored record with identifier ID with its previous version. one step back, no regrets.


πŸ”₯ SEE ALSO πŸ”₯

  • Catmandu::Store
  • Catmandu::Bag

okay that's the whole page bestie, you ate that πŸ’– this was written for perl v5.40.1, dated 2026-01-24, and it's part of the User Contributed Perl Documentation β€” go forth and version your records, main character πŸŒŸπŸ’…πŸ¦‹

πŸ“¦ where this page comes from