Logidze

Cover for Logidze

Services & Skills

Share on

Logidze provides tools for logging DB records changes when using PostgreSQL (>=9.6). Just like audited and paper_trail do, (but faster).

Logidze allows you to create a DB-level log (using triggers) and gives you an API to browse this log. The log is stored with the record itself in JSONB column. No additional tables required.

Usage

Basic API

Your model now has log_data column, which stores changes log.

To retrieve record version at a given time use #at or #at! methods:

post = Post.find(27)

# Show current version
post.log_version #=> 3

# Show log size (number of versions)
post.log_size #=> 3

# Get copy of a record at a given time
post.at(time: 2.days.ago)

# or revert the record itself to the previous state (without committing to DB)
post.at!(time: "2018-04-15 12:00:00")

# If no version found
post.at(time: "1945-05-09 09:00:00") #=> nil

You can also get revision by version number:

post.at(version: 2)

It is also possible to get version for relations:

Post.where(active: true).at(time: 1.month.ago)

You can also get diff from specified time:

post.diff_from(time: 1.hour.ago)
#=> { "id" => 27, "changes" => { "title" => { "old" => "Logidze sucks!", "new" => "Logidze rulz!" } } }

# the same for relations
Post.where(created_at: Time.zone.today.all_day).diff_from(time: 1.hour.ago)

There are also #undo! and #redo! options (and more general #switch_to!):

# Revert record to the previous state (and stores this state in DB)
post.undo!

# You can now user redo! to revert back
post.redo!

# More generally you can revert record to arbitrary version
post.switch_to!(2)

You can initiate reloading of log_data from the DB:

post.reload_log_data # => returns the latest log data value

Track meta information

You can store any meta information you want inside your version (it could be IP address, user agent, etc.). To add it, you should wrap your code with a block:

Logidze.with_meta({ip: request.ip}) do
  post.save!
end

Track responsibility

A special application of meta information is storing the author of the change, which is called Responsible ID. There is more likely that you would like to store the current_user.id that way.

To provide responsible_id you should wrap your code in a block:

Logidze.with_responsible(user.id) do
  post.save!
end

And then to retrieve responsible_id:

post.log_data.responsible_id

Full snapshots

You can instruct Logidze to create a full snapshot instead of a diff for a particular log entry.

It could be useful in combination with .without_logging: first, you perform multiple updates without logging, then
you want to create a log entry with the current state. To do that, you should use the Logidze.with_full_snapshot method:

record = Model.find(params[:id])

Logidze.without_logging do
  # perform multiple write operations with record
end

Logidze.with_full_snapshot do
  record.touch
end

Associations versioning

Logidze also supports associations versioning. This feature is disabled by default (due to the number of edge cases).

Further reading

In the same orbit

Explore more open source projects

Schedule call

Irina Nazarova CEO at Evil Martians

Evil Martians transform growth-stage startups into unicorns, build developer tools, and create open source products. Hire us to design and build your product