https://github.com/infinum/rails_log_book
https://github.com/infinum/rails_log_book
ruby
Last synced: 8 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/infinum/rails_log_book
- Owner: infinum
- License: mit
- Created: 2017-02-20T08:39:32.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2025-08-18T09:53:55.000Z (10 months ago)
- Last Synced: 2025-09-16T12:40:46.966Z (9 months ago)
- Topics: ruby
- Language: Ruby
- Homepage:
- Size: 331 KB
- Stars: 3
- Watchers: 14
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# LogBook
LogBook is a gem that tracks changes on your records. Created for the purpuse of auditing and showing activity log.
For comparison with [paper_\__trail](https://github.com/airblade/paper_trail) and [audited](https://github.com/collectiveidea/audited) see []()
## Supported ORMs
Currently only supports ActiveRecord.
## Instalation
Add to your Gemfile:
``` ruby
gem 'rails_log_book'
```
Then run:
```ruby
rails generate log_book:install
rake db:migrate
```
## Reasoning
We built this gem because others did not offer us what we needed.
Benefits:
- new features ([Squashing](#squashing))
- Explicit (needs to be told when to record, as opposed to paper_trail or audited which always record; ie. do not record stuff done in console)
- Has an inbuilt caching mechanism with `meta` field
- ``meta`` field can also be used to add aditional keys on which search queries can be run
## Usage
Add to models you want to keep track of:
``` ruby
class User < ActiveRecord::Base
include LogBook::Recorder
has_log_book_records
end
```
Add to controlers and actions you want the tracker to be active:
``` ruby
class UsersController < ApplicationController
include LogBook::ControllerRecord
end
```
By default, whenever a user record is created, updated or deleted in any actions of users\_controller a new log\_book record will be created.
## Squashing
The idea of squashing came when we needed to show an activity page where you have a has_many relation setup but you need to show changes only on the "main" object.
Example:
```ruby
class Hotel < ApplicationRecord
include LogBook::Recorder
has_log_book_records
has_many :amenities
accepts_nested_attributes_for :amenities
end
class HotelAmenity < ApplicationRecord
include LogBook::Recorder
has_log_book_records, parent: :hotel
belongs_to :hotel
belongs_to :amenity
end
class Amenity < ApplicationRecord
has_many :hotels
end
class HotelsController < ApplicationController
def create
@hotel = Hotel.create(hotel_params)
end
def hotel_params
params.require(:hotel).permit(amenities_attributes: [:id, :status])
end
end
# having this params passed to hotels_controller:
{ name: 'Hotel', amenitites_attributes: { 0: {id: 1, status: :avaliable}, 1: { id: 4, status: :unavaliable } } }
# Without squashing you would have these records in the DB (abbreviated for clairity)
[
{subject_type: 'Hotel', subject_id: 1, parent_type: nil, parent_id: nil, record_changes: { name: [nil, 'Hotel']}},
{subject_type: 'HotelAmenity', subject_id: 1, parent_type: 'Hotel', parent_id: 1, record_changes: { name: [nil, 'avaliable']}},
{subject_type: 'HotelAmenity', subject_id: 4, parent_type: 'Hotel', parent_id: 1, record_changes: { name: [nil, 'unavaliable']}},
]
# The above is rather difficult to paginate if you want to show changes done on HotelAmenities to show under Hotel.
# With squashing enabled:
[
{
subject_type: 'Hotel',
subject_id: 1,
parent_type: nil,
parent_id: nil,
record_changes: {
name: [nil, 'Hotel'],
hotel_amenitites: {
1: {status: [nil, 'avaliable']},
2: {status: [nil, 'unavaliable']}
}
}
}
]
```
## ActiveRecord Options
### fields
``` ruby
class User < ActiveRecord::Base
include LogBook::Recorder
# all fields
# has_log_book_records
# Only fields
# has_log_book_records only: [:email, :name]
# Ignored fields
# has_log_book_records except: [:password]
# Default ignored fields
# primary_key (id), LogBook.config.ignored_attributes (:created_at, :updated_at)
end
```
### callbacks
``` ruby
class User < ActiveRecord::Base
include LogBook::Recorder
# all events
# has_log_book_records
# Only record on create and destroy (not update)
# has_log_book_records on: [:create, :destroy]
end
```
### parent
Define who is a parent of this object.
``` ruby
class User < ActiveRecord::Base
include LogBook::Recorder
belongs_to :company
# Parent is Company and will be recorded with each user change
# has_log_book_records parent: :company
end
```
### parent_of
Define who this object is a parent of.
``` ruby
class Account < ActiveRecord::Base
include LogBook::Recorder
has_many :user_memberships
has_many :users, through: :user_memberships
end
def UserMembership < ActiveRecord::Base
belongs_to :account
belongs_to :user
end
class User < ActiveRecord::Base
has_one :user_membership
has_one :account, through: :user_membership
# Parent is Company and will be recorded with each user change
# has_log_book_records parent_of: :account
end
```
### meta
Arbitrary column. This is a jsonb field which can have all kinds of information. Useful when you want to cache fields at the exact point of record creation
``` ruby
class User < ActiveRecord::Base
include LogBook::Recorder
# runs `log_book_meta(record)` method to assign to `:meta` field
# has_log_book_records meta: true
# runs `meta_method` method to assing to `:meta` field
# has_log_book_records meta: :meta_method
# runs passed proc to assing to `:meta` field
# has_log_book_records meta: -> { { slug: email.split('@').first } }
end
```
## ActionController options
### current\_author
Defines what method is run when looking for the author for recording
``` ruby
class Admin::UsersController < ActionController::Base
inlcude LogBook::ControllerRecord
# defaults to `current_user`
def current_author
current_admin
end
```
## Configuration
``` ruby
# config/initializers/log_book.rb
LogBook.configure do |config|
config.ignored_attributes = [:updated_at, :created_at]
config.author_method = :current_user
config.record_squashing = false
config.always_record = false
config.skip_if_empty_actions = [:update]
end
```
## Additional methods
``` ruby
LogBook.with_recording {} #=> Enables recording within block
LogBook.author=(author) #=> Records as a different author within block
LogBook.action=(value) #=> Change default action for this request
LogBook.with_record_squashing {} #=> Squashes records within block
LogBook.enable_recording #=> Enables recording from this point
LogBook.disable_recording #=> Disables recording from this point
LogBook.record_squashing_enabled #=> Enables record squashing from this point
LogBook.recording_enabled #=> Returns true if recording is enabled
```
## 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](https://rubygems.org).
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/infinum/log_book. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
## License
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).