version_record provides a handful of tools to make versioning support super straight forward when it needs to be done at the database level. It makes use of ActiveRecord serialization and querying facilities to provide a nice API when dealing with versions. It relies heavily on Semantic Versioning.
Add this line to your application's Gemfile:
gem 'version_record'
And then execute:
$ bundle
Or install it yourself as:
$ gem install version_record
The more straight forward use case for this gem would be for
an application implementing versioning at the database level. Let's
say your application has a documents
table for storing legal
documents, which has a version
column for storing the document
version. Then you could do something like this:
class Document < ActiveRecord::Base
versioned
end
This will generate the following behavior:
document = Document.new(version: '2.0.0')
document.version # => #<VersionRecord::Version:0x007fd171d5c8f8 @major=2, @minor=0, @patch=0, @prerelease=nil>
document.version.to_s # => "2.0.0"
document.version.bump # => "2.1.0"
document.version.bump(:major) # => "3.0.0"
document.version.bump(:patch) # => "3.0.1"
document.save!
It will also generate two helper methods in your model called
by_version
and latest_version
Document.where(title: 'Terms of service').by_version(:desc) # => Will return a sorted list of "Terms of service" documents, ordered by version
Document.where(title: 'Terms of service').latest_version # => Will return the latest "Terms of service" document
WARNING: by_version
and latest_version
are for now considered
inefficient and you should be careful about using them with
large sets of data. They use in-memory sorting, please use them
at your own risk.
Versions are treated seamlessly as normal attributes
Document.create!(version: '1.0.0')
Or you can use setters on objects:
document.version = "1.0.0.beta"
document.version.to_s # => "1.0.0.beta"
Version comparison work as you'd expect, honoring the Semantic Versioning specification:
document_1 = Document.create!(version: '1.0.0')
document_2 = Document.create!(version: '1.1.0')
document_3 = Document.create!(version: '1.1.1.beta')
document_4 = Document.create!(version: '1.1.1')
document_1.version.class # => VersionRecord::Version
document_1.version < document_2.version # => true
document_2.version < document_3.version # => true
document_3.version < document_4.version # => true
ActiveRecord-style querying is supported. Versions are stored as strings in the end, so you can still use normal querying:
Document.where(version: '1.0.0') # => Returns all the documents with version "1.0.0"
Document.find_by_version('2.0.0') # => Finds the document with version "2.0.0"
However, if you need to deal with version objects, this should also work:
document = Document.create!(version: '1.0.0') # => VersionRecord::Version
Document.where(version: document.version) # => Returns all the documents with version "1.0.0"
Document.find_by_version(document.version) # => Finds the document with version "1.0.0"
version_record adds a handy helper for strings:
"1.0.0".to_version # => #<VersionRecord::Version:0x007fd17191bca8...
"1.0.0-rc1".to_version # => #<VersionRecord::Version:0x007fd17191bca8...
"1...1".to_version # => ArgumentError: Malformed version number string 1...1
If your version column is not called version
you can
customize it with the column_name
option. For example,
let's say that the name of your column is semantic_version
instead of version
, then you can do:
class Document < ActiveRecord::Base
versioned column_name: :semantic_version
end
So then calling document.semantic_version
should properly
respond with a version object:
document.semantic_version # => #<VersionRecord::Version:0x007fd171d5c8f8 @major=2, @minor=0, @patch=0, @prerelease=nil>
- Fork it ( https://github.com/cedarcode/version_record/ )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
See the Running Tests guide for details on how to run the test suite.
This project is licensed under the MIT License - see the LICENSE file for details