simple_trail 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Rakefile +28 -0
- data/app/models/simple_trail/application_record.rb +7 -0
- data/app/models/simple_trail/encrypted_history.rb +21 -0
- data/app/models/simple_trail/history.rb +24 -0
- data/config/database.yml +7 -0
- data/db/migrate/20200514201449_create_simple_trails.rb +20 -0
- data/docs/README.md +74 -0
- data/lib/simple_trail/config.rb +30 -0
- data/lib/simple_trail/engine.rb +27 -0
- data/lib/simple_trail/entry_presenter.rb +65 -0
- data/lib/simple_trail/recordable.rb +38 -0
- data/lib/simple_trail/version.rb +6 -0
- data/lib/simple_trail/yaml_unsafe_coder.rb +23 -0
- data/lib/simple_trail.rb +61 -0
- metadata +219 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: db72b8ad5f7f566849b1f65a0ce90dbb9e69957614f794a6d263c8bba6fcbf39
|
|
4
|
+
data.tar.gz: 77ef1d353aa69bfd59f4b70c510b202d1c9212808a2d58db5e694ffcbb69407f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 73c11bee92e240153827cadff106c3b0b8afc7c5f83ed1ac98874c5ba1ed94d55633e8f7845b28521d6888427d4fa308b0c40fa731a6b2dea4adc021eef73ca2
|
|
7
|
+
data.tar.gz: 10a56e91186eb58487ab2a619dc0a6ec59e9406aa610fc8365acbaf34447dc324107aa2bf70a0d1f2229ec6ca3626dc62b9e401c3c9b217ae4cb6439b678bd3c
|
data/Rakefile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "bundler/gem_tasks"
|
|
5
|
+
require "rspec/core/rake_task"
|
|
6
|
+
require "rubocop/rake_task"
|
|
7
|
+
|
|
8
|
+
begin
|
|
9
|
+
require "bundler/setup"
|
|
10
|
+
require "yard"
|
|
11
|
+
YARD::Rake::YardocTask.new do |t|
|
|
12
|
+
t.files = ["lib/**/*.rb"]
|
|
13
|
+
t.files = ["app/models/simple_trail/*.rb"]
|
|
14
|
+
end
|
|
15
|
+
rescue LoadError
|
|
16
|
+
puts "You must `bundle install` to run rake tasks"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
|
|
20
|
+
load "rails/tasks/engine.rake"
|
|
21
|
+
|
|
22
|
+
Bundler::GemHelper.install_tasks
|
|
23
|
+
|
|
24
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
25
|
+
|
|
26
|
+
RuboCop::RakeTask.new(:rubocop)
|
|
27
|
+
|
|
28
|
+
task default: %i[rubocop app:db:prepare spec]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleTrail
|
|
4
|
+
class EncryptedHistory < ::SimpleTrail::History
|
|
5
|
+
extend AttrEncrypted
|
|
6
|
+
|
|
7
|
+
attr_encrypted :note, key: NitroConfig.get_deferred!("encryption_key"),
|
|
8
|
+
encode: true,
|
|
9
|
+
insecure_mode: true,
|
|
10
|
+
algorithm: "aes-256-cbc",
|
|
11
|
+
mode: :single_iv_and_salt
|
|
12
|
+
|
|
13
|
+
before_save :clear_plain_note
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def clear_plain_note
|
|
18
|
+
self[:note] = nil
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleTrail
|
|
4
|
+
class History < ::SimpleTrail::ApplicationRecord
|
|
5
|
+
serialize :source_changes, ::SimpleTrail::YAMLUnsafeCoder
|
|
6
|
+
serialize :backtrace, Array
|
|
7
|
+
|
|
8
|
+
default_scope { order("id DESC") }
|
|
9
|
+
|
|
10
|
+
scope :for_source, ->(source_object) do
|
|
11
|
+
where(source_id: source_object.id, source_type: source_object.class.to_s)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
scope :in_natural_order, -> { reorder("id ASC") }
|
|
15
|
+
|
|
16
|
+
before_create :set_backtrace
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def set_backtrace
|
|
21
|
+
self.backtrace = SimpleTrail::Config.backtrace_cleaner&.clean(caller) || caller
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/config/database.yml
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Metrics/MethodLength
|
|
4
|
+
class CreateSimpleTrails < ActiveRecord::Migration[6.0]
|
|
5
|
+
def change
|
|
6
|
+
create_table :"#{SimpleTrail.table_name_prefix}histories" do |t|
|
|
7
|
+
t.string :source_type
|
|
8
|
+
t.string :source_id
|
|
9
|
+
t.text :source_changes
|
|
10
|
+
t.integer :user_id
|
|
11
|
+
t.text :note
|
|
12
|
+
t.string :activity
|
|
13
|
+
t.text :encrypted_note
|
|
14
|
+
t.text :backtrace
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
add_index :"#{SimpleTrail.table_name_prefix}histories", %i[source_type source_id]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
# rubocop:enable Metrics/MethodLength
|
data/docs/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
## What is SimpleTrail
|
|
2
|
+
|
|
3
|
+
SimpleTrail makes it easy to keep a history of attribute changes on a model
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'simple_trail'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
$ bundle
|
|
16
|
+
|
|
17
|
+
Or install it yourself as:
|
|
18
|
+
|
|
19
|
+
$ gem install simple_trail
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Configuration
|
|
23
|
+
|
|
24
|
+
1. Add SimpleTrail config to your initializer file.
|
|
25
|
+
2. You need to set `current_session_user_id` to include user info in `simple_trail_histories` table.
|
|
26
|
+
3. You can optionally set `table_name_prefix` to customize default table name. Defaults to `simple_trail_histories`.
|
|
27
|
+
4. SimpleTrail stores backtrace info in `simple_trail_histories`. It defaults to `Rails.backtrace_cleaner`. You can optionally set it to your customized backtrace cleaner.
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
SimpleTrail.config do
|
|
31
|
+
table_name_prefix "myapp_"
|
|
32
|
+
current_session_user_id { MyApp.current_session_user_id }
|
|
33
|
+
backtrace_cleaner { YourCustom.backtrace_cleaner }
|
|
34
|
+
end
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
class Project < ApplicationRecord
|
|
41
|
+
include ::SimpleTrail::Recordable
|
|
42
|
+
end
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Inlcude `simple_trail` in your lib files if you need to call it there:
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
require "simple_trail"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
Now you can access the object history through `SimpleTrail.for(object)` like:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
project = Project.create
|
|
56
|
+
SimpleTrail.for(project).size
|
|
57
|
+
# => 1
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The user performing the action will be recorded from the Thread local `:user_id`.
|
|
61
|
+
|
|
62
|
+
Then, require the engine in your `application.rb`
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
require "simple_trail"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Contributing
|
|
69
|
+
|
|
70
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/powerhome/power-tools.
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
The package is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleTrail
|
|
4
|
+
module Config
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
# SimpleTrail Stores backtrace info in `simple_trail_histories`
|
|
8
|
+
# It's config defaults to `Rails.backtrace_cleaner`
|
|
9
|
+
# You can optionally set it to your customized backtrace cleaner
|
|
10
|
+
# via `SimpleTrail.config.backtrace_cleaner = MyBacktraceCleaner`
|
|
11
|
+
mattr_accessor :backtrace_cleaner
|
|
12
|
+
|
|
13
|
+
# Allows to set configurion for SimpleTrail
|
|
14
|
+
def config(&block)
|
|
15
|
+
class_eval(&block)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Optionally set `table_name_prefix` to customize default table name.
|
|
19
|
+
# Defaults to `simple_trail_histories`
|
|
20
|
+
def table_name_prefix(value)
|
|
21
|
+
SimpleTrail.table_name_prefix = value
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Sets `current_session_user_id` to include user info in `simple_trail_histories` table.
|
|
25
|
+
def current_session_user_id(&block)
|
|
26
|
+
@current_session_user_id = block if block
|
|
27
|
+
@current_session_user_id
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleTrail
|
|
4
|
+
class Engine < ::Rails::Engine
|
|
5
|
+
isolate_namespace SimpleTrail
|
|
6
|
+
|
|
7
|
+
config.generators do |g|
|
|
8
|
+
g.test_framework :rspec
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
config.generators do |g|
|
|
12
|
+
g.fixture_replacement :factory_bot, dir: "spec/factories"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
initializer :append_migrations do |app|
|
|
16
|
+
unless app.root.to_s.match? root.to_s
|
|
17
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
|
18
|
+
app.config.paths["db/migrate"] << expanded_path
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
initializer "simple_trail.backtrace_cleaner" do
|
|
24
|
+
SimpleTrail::Config.backtrace_cleaner ||= Rails.backtrace_cleaner
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleTrail
|
|
4
|
+
class EntryPresenter
|
|
5
|
+
delegate :backtrace,
|
|
6
|
+
:created_at,
|
|
7
|
+
:activity,
|
|
8
|
+
:source_type,
|
|
9
|
+
:source_id,
|
|
10
|
+
:source_changes,
|
|
11
|
+
:user_id,
|
|
12
|
+
:user,
|
|
13
|
+
:note,
|
|
14
|
+
:id,
|
|
15
|
+
to: :history, prefix: false
|
|
16
|
+
def initialize(history)
|
|
17
|
+
@history = history
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Details the changes made to the source object.
|
|
21
|
+
def describe_changes
|
|
22
|
+
@history.source_changes.map do |field, change|
|
|
23
|
+
describe_change(field, change)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
attr_reader :history
|
|
30
|
+
|
|
31
|
+
def describe_change(field, change)
|
|
32
|
+
values = change.map { |value| format_value(field, value) }
|
|
33
|
+
return unless values.any?
|
|
34
|
+
|
|
35
|
+
from, to = *values
|
|
36
|
+
to = "nothing" if to.blank?
|
|
37
|
+
build_message(field, from, to)
|
|
38
|
+
rescue
|
|
39
|
+
"#{field}: #{from} - #{to}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def format_value(field, val)
|
|
43
|
+
val = val.strftime("%m/%d/%Y") if val.respond_to?(:strftime)
|
|
44
|
+
val = val.map(&:humanize).join(", ") if val.is_a?(Array) && val.first.is_a?(String)
|
|
45
|
+
val = number_to_currency(val, precision: 2) if numeric?(field, val)
|
|
46
|
+
val
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def build_message(field, from, to)
|
|
50
|
+
if to == true
|
|
51
|
+
"Selected #{field.to_s.titleize}"
|
|
52
|
+
elsif from == true
|
|
53
|
+
"Deselected #{field.to_s.titleize}"
|
|
54
|
+
elsif from.present?
|
|
55
|
+
"Changed #{field.to_s.titleize} from #{from} to #{to}"
|
|
56
|
+
else
|
|
57
|
+
"Changed #{field.to_s.titleize} to #{to}"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def numeric?(field, val)
|
|
62
|
+
field =~ /amount|price|cost|ceiling/i && val.respond_to?(:to_f) && val != ""
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleTrail
|
|
4
|
+
module Recordable
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
around_save :__record_changes
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class_methods do
|
|
12
|
+
attr_reader :__simple_trail_source_changes
|
|
13
|
+
|
|
14
|
+
def history_options(source_changes: nil)
|
|
15
|
+
@__simple_trail_source_changes = source_changes
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def __record_changes
|
|
22
|
+
activity = new_record? ? :created : :updated
|
|
23
|
+
yield
|
|
24
|
+
SimpleTrail.record!(self, activity, __simple_trail_source_changes,
|
|
25
|
+
SimpleTrail::Config.current_session_user_id&.call)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def __simple_trail_source_changes
|
|
29
|
+
source_changes = self.class.__simple_trail_source_changes
|
|
30
|
+
|
|
31
|
+
case source_changes
|
|
32
|
+
when Proc then instance_exec(&source_changes)
|
|
33
|
+
when Symbol then send(source_changes)
|
|
34
|
+
else saved_changes
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleTrail
|
|
4
|
+
module YAMLUnsafeCoder
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
# Loads the object from YAML.
|
|
8
|
+
def load(payload)
|
|
9
|
+
return unless payload
|
|
10
|
+
|
|
11
|
+
if YAML.respond_to?(:unsafe_load)
|
|
12
|
+
YAML.unsafe_load(payload)
|
|
13
|
+
else
|
|
14
|
+
YAML.load(payload) # rubocop:disable Security/YAMLLoad
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Dumps the object to YAML.
|
|
19
|
+
def dump(obj)
|
|
20
|
+
YAML.dump obj
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/simple_trail.rb
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "attr_encrypted"
|
|
4
|
+
require "nitro_config"
|
|
5
|
+
require "simple_trail/engine"
|
|
6
|
+
require "simple_trail/entry_presenter"
|
|
7
|
+
require "simple_trail/recordable"
|
|
8
|
+
require "simple_trail/yaml_unsafe_coder"
|
|
9
|
+
require "simple_trail/config"
|
|
10
|
+
|
|
11
|
+
module SimpleTrail
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
mattr_accessor(:table_name_prefix) { "simple_trail_" }
|
|
15
|
+
|
|
16
|
+
# Allows to set configurion for SimpleTrail
|
|
17
|
+
#
|
|
18
|
+
# SimpleTrail.config do
|
|
19
|
+
# configs to be set
|
|
20
|
+
# end
|
|
21
|
+
def config(...)
|
|
22
|
+
Config.config(...)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Records a history activity for the given object
|
|
26
|
+
#
|
|
27
|
+
# @param object [#id] the object recording a history
|
|
28
|
+
# @param activity [Symbol] the activity that generated the history entry (i.e.: :created)
|
|
29
|
+
# @param changes [Hash] an ActiveRecord changes hash (i.e.: { 'name' => ['old', 'new'] })
|
|
30
|
+
# @param user_id [Integer] the id of the user triggered the history entry
|
|
31
|
+
# @param note [String] a note that can be attached to a history
|
|
32
|
+
# @param encrypted [Boolean] whether to encrypt or not the note
|
|
33
|
+
# @return [SimpleTrail::EntryPresenter]
|
|
34
|
+
|
|
35
|
+
# rubocop:disable Metrics/ParameterLists
|
|
36
|
+
def record!(object, activity, changes, user_id, note = nil, encrypted: false)
|
|
37
|
+
klass = encrypted ? SimpleTrail::EncryptedHistory : SimpleTrail::History
|
|
38
|
+
|
|
39
|
+
history = klass.for_source(object).create!(
|
|
40
|
+
source_changes: changes,
|
|
41
|
+
activity: activity,
|
|
42
|
+
user_id: user_id,
|
|
43
|
+
note: note
|
|
44
|
+
)
|
|
45
|
+
EntryPresenter.new(history)
|
|
46
|
+
end
|
|
47
|
+
# rubocop:enable Metrics/ParameterLists
|
|
48
|
+
|
|
49
|
+
# A collection of the history entries associated with the object
|
|
50
|
+
#
|
|
51
|
+
# @param object [#id] the object recording a history
|
|
52
|
+
# @return [Array<SimpleTrail::EntryPresenter>]
|
|
53
|
+
def for(object, encrypted: false, in_natural_order: false)
|
|
54
|
+
klass = encrypted ? SimpleTrail::EncryptedHistory : SimpleTrail::History
|
|
55
|
+
|
|
56
|
+
history_collection = in_natural_order ? klass.for_source(object).in_natural_order : klass.for_source(object)
|
|
57
|
+
history_collection.to_a.map do |history|
|
|
58
|
+
SimpleTrail::EntryPresenter.new(history)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: simple_trail
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Gurban Haydarov
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2023-03-20 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: nitro_config
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: powerhome-attr_encrypted
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - '='
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 1.2.0
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - '='
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 1.2.0
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rails
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 6.0.6.1
|
|
48
|
+
- - "<"
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: '7.0'
|
|
51
|
+
type: :runtime
|
|
52
|
+
prerelease: false
|
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
54
|
+
requirements:
|
|
55
|
+
- - ">="
|
|
56
|
+
- !ruby/object:Gem::Version
|
|
57
|
+
version: 6.0.6.1
|
|
58
|
+
- - "<"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '7.0'
|
|
61
|
+
- !ruby/object:Gem::Dependency
|
|
62
|
+
name: license_finder
|
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '7.0'
|
|
68
|
+
type: :development
|
|
69
|
+
prerelease: false
|
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '7.0'
|
|
75
|
+
- !ruby/object:Gem::Dependency
|
|
76
|
+
name: rake
|
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '13'
|
|
82
|
+
type: :development
|
|
83
|
+
prerelease: false
|
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '13'
|
|
89
|
+
- !ruby/object:Gem::Dependency
|
|
90
|
+
name: rspec
|
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '3.0'
|
|
96
|
+
type: :development
|
|
97
|
+
prerelease: false
|
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '3.0'
|
|
103
|
+
- !ruby/object:Gem::Dependency
|
|
104
|
+
name: rspec-rails
|
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 5.1.2
|
|
110
|
+
type: :development
|
|
111
|
+
prerelease: false
|
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: 5.1.2
|
|
117
|
+
- !ruby/object:Gem::Dependency
|
|
118
|
+
name: rubocop-powerhome
|
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - '='
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: 0.5.0
|
|
124
|
+
type: :development
|
|
125
|
+
prerelease: false
|
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - '='
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: 0.5.0
|
|
131
|
+
- !ruby/object:Gem::Dependency
|
|
132
|
+
name: simplecov
|
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - '='
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: 0.15.1
|
|
138
|
+
type: :development
|
|
139
|
+
prerelease: false
|
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - '='
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: 0.15.1
|
|
145
|
+
- !ruby/object:Gem::Dependency
|
|
146
|
+
name: sqlite3
|
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - "~>"
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: 1.4.2
|
|
152
|
+
type: :development
|
|
153
|
+
prerelease: false
|
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
155
|
+
requirements:
|
|
156
|
+
- - "~>"
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: 1.4.2
|
|
159
|
+
- !ruby/object:Gem::Dependency
|
|
160
|
+
name: yard
|
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - '='
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: 0.9.21
|
|
166
|
+
type: :development
|
|
167
|
+
prerelease: false
|
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
169
|
+
requirements:
|
|
170
|
+
- - '='
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: 0.9.21
|
|
173
|
+
description: SimpleTrail makes it easy to keep a history of attribute changes on a
|
|
174
|
+
model
|
|
175
|
+
email:
|
|
176
|
+
- gurban@hey.com
|
|
177
|
+
executables: []
|
|
178
|
+
extensions: []
|
|
179
|
+
extra_rdoc_files: []
|
|
180
|
+
files:
|
|
181
|
+
- Rakefile
|
|
182
|
+
- app/models/simple_trail/application_record.rb
|
|
183
|
+
- app/models/simple_trail/encrypted_history.rb
|
|
184
|
+
- app/models/simple_trail/history.rb
|
|
185
|
+
- config/database.yml
|
|
186
|
+
- db/migrate/20200514201449_create_simple_trails.rb
|
|
187
|
+
- docs/README.md
|
|
188
|
+
- lib/simple_trail.rb
|
|
189
|
+
- lib/simple_trail/config.rb
|
|
190
|
+
- lib/simple_trail/engine.rb
|
|
191
|
+
- lib/simple_trail/entry_presenter.rb
|
|
192
|
+
- lib/simple_trail/recordable.rb
|
|
193
|
+
- lib/simple_trail/version.rb
|
|
194
|
+
- lib/simple_trail/yaml_unsafe_coder.rb
|
|
195
|
+
homepage: https://github.com/powerhome/power-tools
|
|
196
|
+
licenses:
|
|
197
|
+
- MIT
|
|
198
|
+
metadata:
|
|
199
|
+
rubygems_mfa_required: 'true'
|
|
200
|
+
post_install_message:
|
|
201
|
+
rdoc_options: []
|
|
202
|
+
require_paths:
|
|
203
|
+
- lib
|
|
204
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
205
|
+
requirements:
|
|
206
|
+
- - ">="
|
|
207
|
+
- !ruby/object:Gem::Version
|
|
208
|
+
version: '2.7'
|
|
209
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
210
|
+
requirements:
|
|
211
|
+
- - ">="
|
|
212
|
+
- !ruby/object:Gem::Version
|
|
213
|
+
version: '0'
|
|
214
|
+
requirements: []
|
|
215
|
+
rubygems_version: 3.4.6
|
|
216
|
+
signing_key:
|
|
217
|
+
specification_version: 4
|
|
218
|
+
summary: Simple way to track database changes
|
|
219
|
+
test_files: []
|