Gem Version CircleCI codecov

ActsAsTracked

Welcome to ActsAsTracked! This gem is an extension to your ActiveRecord models to track activities. It does not track everything all the time or in the background, but can be used wherever you find it necessary to have a history for changes alongside their actors.

There are few other gems such as audited, however, it is tracking every change on your models. ActsAsTracked is controlled by you and will track changes only when used explicitly.

Installation

Add this line to your application's Gemfile:

gem 'acts_as_tracked'

And then execute:

bundle install

Or install it yourself as:

gem install acts_as_tracked

Usage

Create Activities table

First, you would need to generate a migration to create Activities table in your database.

ActsAsTracked has extension to generate migrations. Please, run:

  bundle exec rails generate acts_as_tracked:migration

This will generate following migration:

class ActsAsTrackedMigration < ActiveRecord::Migration
  def self.up
    create_table :activities do |t|
      t.references :actor, polymorphic: true
      t.references :subject, polymorphic: true
      t.references :parent, polymorphic: true
      t.text :attribute_changes
      t.string :activity_type
      t.string :human_description
      t.timestamps null: false
    end
  end

  def self.down
    drop_table :activity
  end
end

Run bundle exec rails db:migrate and let's move on to the usage.

Call acts_as_tracked in your AR model

If you would like to track changes of Post model, you would need to call acts_as_tracked in it.

  class Post < ApplicationRecord
    acts_as_tracked

    # You may optionally pass in exluded_activity_attributes
    # as an argument to not track given fields.
    #
    # acts_as_tracked(exclude_activity_attributes: %i[api_key, username])
  end

Tracking Changes

Now, you are able to track changes on Post.

@post = Post.first

Post.tracking_changes(actor: User.find(1)) do
  @post.update(
    content: 'New Content'
  )  
end

Let's try to get activities for Post we just changed:

@post.activities

[
  #<ActsAsTracked::Activity:0x000056475df12840
  id: 1,
  actor_id: 1,
  actor_type: "User",
  subject_id: 2,
  subject_type: "Post",
  parent_id: nil,
  parent_type: nil,
  attribute_changes: {"content"=>["Great post content.", "New Content"]},
  activity_type: "updated",
  human_description: nil,
  created_at: Thu, 25 Jun 2020 12:03:39 UTC +00:00,
  updated_at: Thu, 25 Jun 2020 12:03:39 UTC +00:00>
]

More features

You can check activities for the record in which it was an Actor:

@post.activities_as_actor

...activities

You can check activities for the record in which it was a Subject:

@post.activities_as_subject

...activities

You can check activities for collection of records by passing ids:

Post.activities_for([post_id1, post_id2])

...activities

Extra options to pass to tracking_changes call

tracking_changes method can accept 3 arguments:

  1. actor: mandatory -> actor record
  2. subject: optional -> acting on record, defaults to record you are changing
  3. parent: optional -> parent record for acting on record, defaults to nil
  4. human_description: optional -> description you would like to include on change, defaults to nil
Post.tracking_changes(actor: User.first, subject: Post.first, human_description: 'Some description of change', parent: Post.first.parent) do
...your changes here
end

Excluding attributes from change sets

Sometimes you would like to not track some fields of the record in change sets.

You can use exclude_activity_attributes and ActsAsTracked will not include them in activities.

  class Post < ApplicationRecord
    acts_as_tracked(exclude_activity_attributes: %i[api_key, username])
  end

Differences between PaperTrail, Audited, and PublicActivity gems

Main difference is that ActsAsTracked does not track anything unless used explicitly. It does not store versions of the record that you can rollback to.

It's minimal, and only does 1 thing, that is creating activity records with change sets whenever used.

It's a feature extension to your models to use when needed, instead of being a hook that acts in the background.

Post.tracking_changes(actor: @user) do
  ...changes on posts
end

You can check the tracking module which is just a shy over 100 lines that gets plugged in your models here.

Example application using ActsAsTracked

I have created a Rails 6 application with the usages of ActsAsTracked. Please refer to this repo

Credits

Initial work of ActsAsTracked has been done by @rogercampos and @camaloon team. I have refined, packaged, documented, added generators and published it.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then 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 rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/ramblingcode/acts-as-tracked. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the ActsAsTracked project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.