snapcher 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d135b4fe2eb8e197ce54999308444dff97dcce48be81085900c3ab0f31630a01
4
- data.tar.gz: 39561cc6337d078b96c55bf8eb01bb3682f9691e32d9c899f14d5efd7fc19a7d
3
+ metadata.gz: cf06ee5a1a0a2a88b36aaf158a7968e6e43e076d48c5109312f299b00dd84f75
4
+ data.tar.gz: 0005bf88e3a4e16762aec1ba059a327bdb2c5e01e97f9727a5a4ac60db1abf42
5
5
  SHA512:
6
- metadata.gz: 862907d00cd9ced9f372a6ea76816ee05b43ed2d5689edc5b6886232697c4e5c9dea0f55671547a6c703f356cebf2aeccc795da3fb49ebabedd243c8989ef30a
7
- data.tar.gz: 191d10f000330f07fda6c60fe54747f413149063182edd59808e289eb60e3073e14368dbdd1070d6a8fd57b6624d29af984ead148aebdfd5e11ab75c747fa793
6
+ metadata.gz: b9377f8a832c2ca08c13b9cdeb05651be64672d7058a96e8bf36ca82fb5b2142e8cc3f48c15f2555011dca32ab409ab20119c07e1822ca6b12e77f3efc30257b
7
+ data.tar.gz: e7c95f86a999f0000686f5a9f4afc55af69b0fc3cd451e8a9cf1d1970f1c06d50a14cefdfe72a9c0e057f1e012c0c1f1fd9240562446ee1141ee0298023e103e
data/.rubocop.yml CHANGED
@@ -1,5 +1,14 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ inherit_gem:
4
+ rubocop-discourse: default.yml
5
+
1
6
  AllCops:
2
- TargetRubyVersion: 2.6
7
+ TargetRubyVersion: 3.2
8
+ NewCops: disable
9
+ Exclude:
10
+ - lib/generators/snapcher/templates/install.rb
11
+ - sample-app/bin/bundle
3
12
 
4
13
  Style/StringLiterals:
5
14
  Enabled: true
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,78 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config --exclude-limit 999999`
3
+ # on 2023-10-23 18:48:06 UTC using RuboCop version 1.57.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ Discourse/NoChdir:
11
+ Exclude:
12
+ - 'spec/**/*'
13
+ - 'plugins/*/spec/**/*'
14
+ - 'snapcher.gemspec'
15
+
16
+ # Offense count: 1
17
+ # This cop supports safe autocorrection (--autocorrect).
18
+ # Configuration parameters: EnforcedStyleAlignWith, Severity.
19
+ # SupportedStylesAlignWith: keyword, variable, start_of_line
20
+ Layout/EndAlignment:
21
+ Exclude:
22
+ - 'lib/snapcher/junker.rb'
23
+
24
+ # Offense count: 1
25
+ # This cop supports safe autocorrection (--autocorrect).
26
+ # Configuration parameters: Width, AllowedPatterns.
27
+ Layout/IndentationWidth:
28
+ Exclude:
29
+ - 'lib/snapcher/junker.rb'
30
+
31
+ # Offense count: 2
32
+ # This cop supports safe autocorrection (--autocorrect).
33
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
34
+ # SupportedStyles: aligned, indented, indented_relative_to_receiver
35
+ Layout/MultilineMethodCallIndentation:
36
+ Exclude:
37
+ - 'sample-app/config/environments/production.rb'
38
+
39
+ # Offense count: 34
40
+ # This cop supports unsafe autocorrection (--autocorrect-all).
41
+ # Configuration parameters: EnforcedStyle.
42
+ # SupportedStyles: always, always_true, never
43
+ Style/FrozenStringLiteralComment:
44
+ Exclude:
45
+ - 'lib/generators/snapcher/install/install_generator.rb'
46
+ - 'sample-app/Gemfile'
47
+ - 'sample-app/Rakefile'
48
+ - 'sample-app/app/controllers/application_controller.rb'
49
+ - 'sample-app/app/helpers/application_helper.rb'
50
+ - 'sample-app/app/jobs/application_job.rb'
51
+ - 'sample-app/app/models/application_record.rb'
52
+ - 'sample-app/app/models/user.rb'
53
+ - 'sample-app/bin/rails'
54
+ - 'sample-app/bin/rake'
55
+ - 'sample-app/bin/setup'
56
+ - 'sample-app/config.ru'
57
+ - 'sample-app/config/application.rb'
58
+ - 'sample-app/config/boot.rb'
59
+ - 'sample-app/config/environment.rb'
60
+ - 'sample-app/config/environments/development.rb'
61
+ - 'sample-app/config/environments/production.rb'
62
+ - 'sample-app/config/environments/test.rb'
63
+ - 'sample-app/config/initializers/assets.rb'
64
+ - 'sample-app/config/initializers/content_security_policy.rb'
65
+ - 'sample-app/config/initializers/filter_parameter_logging.rb'
66
+ - 'sample-app/config/initializers/inflections.rb'
67
+ - 'sample-app/config/initializers/permissions_policy.rb'
68
+ - 'sample-app/config/puma.rb'
69
+ - 'sample-app/config/routes.rb'
70
+ - 'sample-app/db/migrate/20231019150803_create_users.rb'
71
+ - 'sample-app/db/schema.rb'
72
+ - 'sample-app/db/seeds.rb'
73
+ - 'spec/rails_app/config/application.rb'
74
+ - 'spec/rails_app/config/environment.rb'
75
+ - 'spec/rails_app/config/environments/test.rb'
76
+ - 'spec/rails_app/config/routes.rb'
77
+ - 'spec/support/active_record/models.rb'
78
+ - 'spec/support/active_record/schema.rb'
data/Gemfile CHANGED
@@ -3,10 +3,14 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  # Specify your gem's dependencies in snapcher.gemspec
6
- gemspec
6
+ gemspec name: "snapcher"
7
7
 
8
+ gem "debug", ">= 1.8.0"
9
+ gem "rails", ">= 7.0.0", "< 7.1"
10
+ gem "railties", require: false
8
11
  gem "rake", "~> 13.0"
9
-
10
12
  gem "rspec", "~> 3.0"
11
-
13
+ gem "rspec-rails", "~> 6.0.0"
14
+ gem "rubocop-discourse", "~> 3.4.0"
12
15
  gem "rubocop", "~> 1.21"
16
+ gem "sqlite3", ">= 1.4"
data/Gemfile.lock CHANGED
@@ -1,24 +1,168 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- snapcher (0.1.0)
4
+ snapcher (0.1.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ actioncable (7.0.8)
10
+ actionpack (= 7.0.8)
11
+ activesupport (= 7.0.8)
12
+ nio4r (~> 2.0)
13
+ websocket-driver (>= 0.6.1)
14
+ actionmailbox (7.0.8)
15
+ actionpack (= 7.0.8)
16
+ activejob (= 7.0.8)
17
+ activerecord (= 7.0.8)
18
+ activestorage (= 7.0.8)
19
+ activesupport (= 7.0.8)
20
+ mail (>= 2.7.1)
21
+ net-imap
22
+ net-pop
23
+ net-smtp
24
+ actionmailer (7.0.8)
25
+ actionpack (= 7.0.8)
26
+ actionview (= 7.0.8)
27
+ activejob (= 7.0.8)
28
+ activesupport (= 7.0.8)
29
+ mail (~> 2.5, >= 2.5.4)
30
+ net-imap
31
+ net-pop
32
+ net-smtp
33
+ rails-dom-testing (~> 2.0)
34
+ actionpack (7.0.8)
35
+ actionview (= 7.0.8)
36
+ activesupport (= 7.0.8)
37
+ rack (~> 2.0, >= 2.2.4)
38
+ rack-test (>= 0.6.3)
39
+ rails-dom-testing (~> 2.0)
40
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
41
+ actiontext (7.0.8)
42
+ actionpack (= 7.0.8)
43
+ activerecord (= 7.0.8)
44
+ activestorage (= 7.0.8)
45
+ activesupport (= 7.0.8)
46
+ globalid (>= 0.6.0)
47
+ nokogiri (>= 1.8.5)
48
+ actionview (7.0.8)
49
+ activesupport (= 7.0.8)
50
+ builder (~> 3.1)
51
+ erubi (~> 1.4)
52
+ rails-dom-testing (~> 2.0)
53
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
54
+ activejob (7.0.8)
55
+ activesupport (= 7.0.8)
56
+ globalid (>= 0.3.6)
57
+ activemodel (7.0.8)
58
+ activesupport (= 7.0.8)
59
+ activerecord (7.0.8)
60
+ activemodel (= 7.0.8)
61
+ activesupport (= 7.0.8)
62
+ activestorage (7.0.8)
63
+ actionpack (= 7.0.8)
64
+ activejob (= 7.0.8)
65
+ activerecord (= 7.0.8)
66
+ activesupport (= 7.0.8)
67
+ marcel (~> 1.0)
68
+ mini_mime (>= 1.1.0)
69
+ activesupport (7.0.8)
70
+ concurrent-ruby (~> 1.0, >= 1.0.2)
71
+ i18n (>= 1.6, < 2)
72
+ minitest (>= 5.1)
73
+ tzinfo (~> 2.0)
9
74
  ast (2.4.2)
10
75
  base64 (0.1.1)
76
+ builder (3.2.4)
77
+ concurrent-ruby (1.2.2)
78
+ crass (1.0.6)
79
+ date (3.3.3)
80
+ debug (1.8.0)
81
+ irb (>= 1.5.0)
82
+ reline (>= 0.3.1)
11
83
  diff-lcs (1.5.0)
84
+ erubi (1.12.0)
85
+ globalid (1.2.1)
86
+ activesupport (>= 6.1)
87
+ i18n (1.14.1)
88
+ concurrent-ruby (~> 1.0)
89
+ io-console (0.6.0)
90
+ irb (1.8.3)
91
+ rdoc
92
+ reline (>= 0.3.8)
12
93
  json (2.6.3)
13
94
  language_server-protocol (3.17.0.3)
95
+ loofah (2.21.4)
96
+ crass (~> 1.0.2)
97
+ nokogiri (>= 1.12.0)
98
+ mail (2.8.1)
99
+ mini_mime (>= 0.1.1)
100
+ net-imap
101
+ net-pop
102
+ net-smtp
103
+ marcel (1.0.2)
104
+ method_source (1.0.0)
105
+ mini_mime (1.1.5)
106
+ minitest (5.20.0)
107
+ net-imap (0.4.2)
108
+ date
109
+ net-protocol
110
+ net-pop (0.1.2)
111
+ net-protocol
112
+ net-protocol (0.2.1)
113
+ timeout
114
+ net-smtp (0.4.0)
115
+ net-protocol
116
+ nio4r (2.5.9)
117
+ nokogiri (1.15.4-arm64-darwin)
118
+ racc (~> 1.4)
119
+ nokogiri (1.15.4-x86_64-linux)
120
+ racc (~> 1.4)
14
121
  parallel (1.23.0)
15
122
  parser (3.2.2.4)
16
123
  ast (~> 2.4.1)
17
124
  racc
125
+ psych (5.1.1.1)
126
+ stringio
18
127
  racc (1.7.1)
128
+ rack (2.2.8)
129
+ rack-test (2.1.0)
130
+ rack (>= 1.3)
131
+ rails (7.0.8)
132
+ actioncable (= 7.0.8)
133
+ actionmailbox (= 7.0.8)
134
+ actionmailer (= 7.0.8)
135
+ actionpack (= 7.0.8)
136
+ actiontext (= 7.0.8)
137
+ actionview (= 7.0.8)
138
+ activejob (= 7.0.8)
139
+ activemodel (= 7.0.8)
140
+ activerecord (= 7.0.8)
141
+ activestorage (= 7.0.8)
142
+ activesupport (= 7.0.8)
143
+ bundler (>= 1.15.0)
144
+ railties (= 7.0.8)
145
+ rails-dom-testing (2.2.0)
146
+ activesupport (>= 5.0.0)
147
+ minitest
148
+ nokogiri (>= 1.6)
149
+ rails-html-sanitizer (1.6.0)
150
+ loofah (~> 2.21)
151
+ nokogiri (~> 1.14)
152
+ railties (7.0.8)
153
+ actionpack (= 7.0.8)
154
+ activesupport (= 7.0.8)
155
+ method_source
156
+ rake (>= 12.2)
157
+ thor (~> 1.0)
158
+ zeitwerk (~> 2.5)
19
159
  rainbow (3.1.1)
20
160
  rake (13.0.6)
161
+ rdoc (6.5.0)
162
+ psych (>= 4.0.0)
21
163
  regexp_parser (2.8.2)
164
+ reline (0.3.9)
165
+ io-console (~> 0.5)
22
166
  rexml (3.2.6)
23
167
  rspec (3.12.0)
24
168
  rspec-core (~> 3.12.0)
@@ -32,6 +176,14 @@ GEM
32
176
  rspec-mocks (3.12.6)
33
177
  diff-lcs (>= 1.2.0, < 2.0)
34
178
  rspec-support (~> 3.12.0)
179
+ rspec-rails (6.0.3)
180
+ actionpack (>= 6.1)
181
+ activesupport (>= 6.1)
182
+ railties (>= 6.1)
183
+ rspec-core (~> 3.12)
184
+ rspec-expectations (~> 3.12)
185
+ rspec-mocks (~> 3.12)
186
+ rspec-support (~> 3.12)
35
187
  rspec-support (3.12.1)
36
188
  rubocop (1.57.1)
37
189
  base64 (~> 0.1.1)
@@ -47,17 +199,46 @@ GEM
47
199
  unicode-display_width (>= 2.4.0, < 3.0)
48
200
  rubocop-ast (1.29.0)
49
201
  parser (>= 3.2.1.0)
202
+ rubocop-capybara (2.19.0)
203
+ rubocop (~> 1.41)
204
+ rubocop-discourse (3.4.0)
205
+ rubocop (>= 1.1.0)
206
+ rubocop-rspec (>= 2.0.0)
207
+ rubocop-factory_bot (2.24.0)
208
+ rubocop (~> 1.33)
209
+ rubocop-rspec (2.24.1)
210
+ rubocop (~> 1.33)
211
+ rubocop-capybara (~> 2.17)
212
+ rubocop-factory_bot (~> 2.22)
50
213
  ruby-progressbar (1.13.0)
214
+ sqlite3 (1.6.7-arm64-darwin)
215
+ sqlite3 (1.6.7-x86_64-linux)
216
+ stringio (3.0.8)
217
+ thor (1.3.0)
218
+ timeout (0.4.0)
219
+ tzinfo (2.0.6)
220
+ concurrent-ruby (~> 1.0)
51
221
  unicode-display_width (2.5.0)
222
+ websocket-driver (0.7.6)
223
+ websocket-extensions (>= 0.1.0)
224
+ websocket-extensions (0.1.5)
225
+ zeitwerk (2.6.12)
52
226
 
53
227
  PLATFORMS
54
228
  arm64-darwin-22
229
+ x86_64-linux
55
230
 
56
231
  DEPENDENCIES
232
+ debug (>= 1.8.0)
233
+ rails (>= 7.0.0, < 7.1)
234
+ railties
57
235
  rake (~> 13.0)
58
236
  rspec (~> 3.0)
237
+ rspec-rails (~> 6.0.0)
59
238
  rubocop (~> 1.21)
239
+ rubocop-discourse (~> 3.4.0)
60
240
  snapcher!
241
+ sqlite3 (>= 1.4)
61
242
 
62
243
  BUNDLED WITH
63
244
  2.4.10
data/README.md CHANGED
@@ -1,39 +1,78 @@
1
+ ![snapcher_logo](https://github.com/ryosk7/snapcher/blob/0-1-2/logo/snapcher_logo.png?raw=true)
2
+
3
+ ----------
4
+
1
5
  # Snapcher
6
+ [![Gem Version](https://img.shields.io/gem/v/snapcher.svg)](http://rubygems.org/gems/snapcher)
7
+ ![GitHub](https://img.shields.io/github/license/ryosk7/snapcher)
8
+ =======
2
9
 
3
- TODO: Delete this and the text below, and describe your gem
10
+ **Snapcher** is an ORM extension that logs changes to specific columns to your model.
4
11
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/snapcher`. To experiment with that code, run `bin/console` for an interactive prompt.
12
+ When a change is made to a specific column, the difference between before and after the change is obtained and saved.
6
13
 
7
- ## Installation
14
+ To make it easier for analysts, save the table name, column name, and data before and after changes as separate columns.
8
15
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
16
+ ## Supported
10
17
 
11
- Install the gem and add to the application's Gemfile by executing:
18
+ ### Snapcher supports Ruby versions:
12
19
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
20
+ * 3.1
21
+ * 3.2
14
22
 
15
- If bundler is not being used to manage dependencies, install the gem by executing:
23
+ ### Snapcher supports Rails versions:
16
24
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
25
+ * 7.0
26
+ * 7.1
18
27
 
19
- ## Usage
28
+ ## Supported ORMs
29
+
30
+ Snapcher is currently ActiveRecord-only.
20
31
 
21
- TODO: Write usage instructions here
32
+ ## Installation
33
+
34
+ Add the gem to your Gemfile:
35
+
36
+ ```ruby
37
+ gem "snapcher"
38
+ ```
22
39
 
23
- ## Development
40
+ Then, from your Rails app directory, create the `scannings` table:
24
41
 
25
- 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.
42
+ ```bash
43
+ $ rails generate snapcher:install
44
+ $ rails db:migrate
45
+ ```
46
+
47
+ ## Usage
26
48
 
27
- 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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
49
+ Simply call `scanning` on your models.
28
50
 
29
- ## Contributing
51
+ Use `column_name:` to select the column you want to log.
30
52
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/snapcher. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/snapcher/blob/main/CODE_OF_CONDUCT.md).
53
+ ```ruby
54
+ class User < ActiveRecord::Base
55
+ scanning column_name: "name"
56
+ end
57
+ ```
32
58
 
33
- ## License
59
+ By default, whenever a user is created, updated or destroyed, a new scanning is created.
34
60
 
35
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
61
+ ```ruby
62
+ user = User.create!(name: "Gillian Seed")
63
+ user.scannings.count # => 1
64
+ user.update!(name: "Mika Slayton")
65
+ user.scannings.count # => 2
66
+ user.destroy
67
+ user.scannings.count # => 3
68
+ ```
36
69
 
37
- ## Code of Conduct
70
+ Scanning contain information regarding what action was taken on the model and what changes were made.
38
71
 
39
- Everyone interacting in the Snapcher project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/snapcher/blob/main/CODE_OF_CONDUCT.md).
72
+ ```ruby
73
+ user.update!(name: "Mika Slayton")
74
+ snapcher = user.scannings.last
75
+ snapcher.action # => "update"
76
+ snapcher.before_params # => "Gillian Seed"
77
+ snapcher.after_params # => "Mika Slayton"
78
+ ```
data/Rakefile CHANGED
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bundler/gem_helper"
3
4
  require "bundler/gem_tasks"
4
5
  require "rspec/core/rake_task"
5
6
 
7
+ Bundler::GemHelper.install_tasks(name: "snapcher")
8
+
6
9
  RSpec::Core::RakeTask.new(:spec)
7
10
 
8
11
  require "rubocop/rake_task"
@@ -7,7 +7,7 @@ module Snapcher
7
7
  class InstallGenerator < ::Rails::Generators::Base
8
8
  include Rails::Generators::Migration
9
9
 
10
- source_root File.expand_path("../../templates", __FILE__)
10
+ source_root File.expand_path("../templates", __dir__)
11
11
 
12
12
  def copy_migration
13
13
  migration_template "install.rb", "db/migrate/install_snapcher.rb"
@@ -24,13 +24,15 @@ module Snapcher
24
24
  end
25
25
 
26
26
  def self.timestamped_migrations?
27
- (Rails.version >= "7.0") ?
28
- ::ActiveRecord.timestamped_migrations :
27
+ if Rails.version >= "7.0"
28
+ ::ActiveRecord.timestamped_migrations
29
+ else
29
30
  ::ActiveRecord::Base.timestamped_migrations
31
+ end
30
32
  end
31
33
 
32
34
  def migration_parent
33
35
  "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
34
36
  end
35
37
  end
36
- end
38
+ end
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "debug"
4
+
3
5
  module Snapcher
4
6
  module Junker
5
7
  extend ActiveSupport::Concern
6
8
 
7
- CALLBACKS = [:scanning_create, :scanning_update, :scanning_destroy]
9
+ CALLBACKS = %i[scanning_create scanning_update scanning_destroy]
8
10
 
9
11
  module ClassMethods
10
12
  def scanning(options = {})
@@ -15,7 +17,9 @@ module Snapcher
15
17
 
16
18
  self.snapcher_options = options
17
19
 
18
- has_many :scannings, -> { order(version: :asc) }, as: :scannable, class_name: "Snapcher::Scanning", inverse_of: :scannable
20
+ has_many :scannings, lambda {
21
+ order(id: :asc)
22
+ }, as: :scannable, class_name: "Snapcher::Scanning", inverse_of: :scannable
19
23
 
20
24
  after_create :scanning_create
21
25
  before_update :scanning_update
@@ -27,19 +31,27 @@ module Snapcher
27
31
 
28
32
  module ScanningInstanceMethods
29
33
  def scanning_create
30
- run_scanning(action: "create", column_name: self.snapcher_options[:column_name], after_params: snapcher_attributes[self.snapcher_options[:column_name]], table_name: self.class.table_name)
34
+ run_scanning(action: "create",
35
+ column_name: snapcher_options[:column_name],
36
+ after_params: snapcher_attributes[snapcher_options[:column_name]],
37
+ table_name: self.class.table_name)
31
38
  end
32
39
 
33
40
  def scanning_update
34
- if (changes = snapcher_changes).present?
35
- run_scanning(action: "update", column_name: self.snapcher_options[:column_name], table_name: self.class.table_name, before_params: snapcher_changes[:before_params], after_params: snapcher_changes[:after_params])
36
- end
41
+ return unless (changes = snapcher_changes).present?
42
+
43
+ run_scanning(action: "update",
44
+ column_name: snapcher_options[:column_name],
45
+ table_name: self.class.table_name,
46
+ before_params: snapcher_changes[:before_params],
47
+ after_params: snapcher_changes[:after_params])
37
48
  end
38
49
 
39
50
  def scanning_destroy
40
- unless new_record?
41
- run_scanning(action: "destroy", column_name: self.snapcher_options[:column_name], table_name: self.class.table_name)
42
- end
51
+ return if new_record?
52
+
53
+ run_scanning(action: "destroy", column_name: snapcher_options[:column_name],
54
+ table_name: self.class.table_name)
43
55
  end
44
56
 
45
57
  # List of attributes that are snapcher.
@@ -50,10 +62,10 @@ module Snapcher
50
62
 
51
63
  def scanning_change_values
52
64
  all_changes = if respond_to?(:changes_to_save)
53
- changes_to_save
54
- else
55
- changes
56
- end
65
+ changes_to_save
66
+ else
67
+ changes
68
+ end
57
69
 
58
70
  filtered_changes = filter_encrypted_attrs(all_changes)
59
71
  filtered_changes = normalize_enum_changes(filtered_changes)
@@ -63,20 +75,20 @@ module Snapcher
63
75
  def snapcher_changes
64
76
  filtered_changes = scanning_change_values
65
77
 
66
- monitoring_column_name = self.snapcher_options[:column_name]
78
+ monitoring_column_name = snapcher_options[:column_name]
67
79
 
68
80
  return if filtered_changes[monitoring_column_name.to_s].nil?
69
81
 
70
82
  before_params = filtered_changes[monitoring_column_name.to_s][0]
71
83
  after_params = filtered_changes[monitoring_column_name.to_s][1]
72
- {before_params: before_params, after_params: after_params}
84
+ { before_params:, after_params: }
73
85
  end
74
86
 
75
87
  def run_scanning(attrs)
76
- run_callbacks(:scanning) {
88
+ run_callbacks(:scanning) do
77
89
  scanning = scannings.create(attrs)
78
90
  scanning
79
- }
91
+ end
80
92
  end
81
93
 
82
94
  def filter_encrypted_attrs(filtered_changes)
@@ -4,12 +4,8 @@ module Snapcher
4
4
  class Railtie < Rails::Railtie
5
5
  initializer "snapcher.sweeper" do
6
6
  ActiveSupport.on_load(:action_controller) do
7
- if defined?(ActionController::Base)
8
- ActionController::Base.around_action Snapcher::Sweeper.new
9
- end
10
- if defined?(ActionController::API)
11
- ActionController::API.around_action Snapcher::Sweeper.new
12
- end
7
+ ActionController::Base.around_action Snapcher::Sweeper.new if defined?(ActionController::Base)
8
+ ActionController::API.around_action Snapcher::Sweeper.new if defined?(ActionController::API)
13
9
  end
14
10
  end
15
11
  end
@@ -6,6 +6,8 @@ module Snapcher
6
6
 
7
7
  cattr_accessor :snapcher_class_names
8
8
 
9
- scope :scannable_finder, ->(scannable_id, scannable_type) { where(scannable_id: scannable_id, scannable_type: scannable_type) }
9
+ scope :scannable_finder, lambda { |scannable_id, scannable_type|
10
+ where(scannable_id:, scannable_type:)
11
+ }
10
12
  end
11
13
  end
@@ -20,7 +20,9 @@ module Snapcher
20
20
  end
21
21
 
22
22
  def current_user
23
- lambda { controller.send(Snapcher.current_user_method) if controller.respond_to?(Snapcher.current_user_method, true) }
23
+ lambda {
24
+ controller.send(Snapcher.current_user_method) if controller.respond_to?(Snapcher.current_user_method, true)
25
+ }
24
26
  end
25
27
 
26
28
  def remote_ip
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Snapcher
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/snapcher.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_record"
4
- require_relative "snapcher/version"
5
4
 
6
5
  module Snapcher
7
6
  class Error < StandardError; end
@@ -12,7 +11,8 @@ module Snapcher
12
11
  attr_writer :scanning_class
13
12
 
14
13
  def scanning_class
15
- # The scanning_class is set as String in the initializer. It can not be constantized during initialization and must
14
+ # The scanning_class is set as String in the initializer.
15
+ # It can not be constantized during initialization and must
16
16
  # be constantized at runtime.
17
17
  @scanning_class = @scanning_class.safe_constantize if @scanning_class.is_a?(String)
18
18
  @scanning_class ||= Snapcher::Scanning
@@ -27,4 +27,6 @@ ActiveSupport.on_load :active_record do
27
27
  include Snapcher::Junker
28
28
  end
29
29
 
30
- require "snapcher/railtie"
30
+ require "snapcher/sweeper"
31
+ require_relative "snapcher/railtie" if defined?(Rails::Railtie)
32
+ # require "snapcher/railtie"
Binary file
data/sample-app/Gemfile CHANGED
@@ -2,22 +2,21 @@ source "https://rubygems.org"
2
2
 
3
3
  ruby "3.2.2"
4
4
 
5
+ gem "jbuilder"
6
+ gem "puma", ">= 5.0"
5
7
  gem "rails", "~> 7.1.1"
6
8
  gem "sprockets-rails"
7
9
  gem "sqlite3", "~> 1.4"
8
- gem "puma", ">= 5.0"
9
- gem "jbuilder"
10
10
 
11
11
  gem "snapcher", path: "../"
12
12
 
13
- gem "tzinfo-data", platforms: %i[ windows jruby ]
14
13
  gem "bootsnap", require: false
14
+ gem "tzinfo-data", platforms: %i[windows jruby]
15
15
 
16
16
  group :development, :test do
17
- gem "debug", platforms: %i[ mri windows ]
17
+ gem "debug", platforms: %i[mri windows]
18
18
  end
19
19
 
20
20
  group :development do
21
21
  gem "web-console"
22
22
  end
23
-
@@ -24,14 +24,14 @@ m = Module.new do
24
24
  def cli_arg_version
25
25
  return unless invoked_as_script? # don't want to hijack other binstubs
26
26
  return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27
+
27
28
  bundler_version = nil
28
29
  update_index = nil
29
30
  ARGV.each_with_index do |a, i|
30
- if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31
- bundler_version = a
32
- end
31
+ bundler_version = a if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
33
32
  next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34
- bundler_version = $1
33
+
34
+ bundler_version = Regexp.last_match(1)
35
35
  update_index = i
36
36
  end
37
37
  bundler_version
@@ -55,8 +55,10 @@ m = Module.new do
55
55
 
56
56
  def lockfile_version
57
57
  return unless File.file?(lockfile)
58
+
58
59
  lockfile_contents = File.read(lockfile)
59
60
  return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
61
+
60
62
  Regexp.last_match(1)
61
63
  end
62
64
 
@@ -86,10 +88,14 @@ m = Module.new do
86
88
  gem "bundler", bundler_requirement
87
89
  end
88
90
  return if gem_error.nil?
91
+
89
92
  require_error = activation_error_handling do
90
93
  require "bundler/version"
91
94
  end
92
- return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
95
+ if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
96
+ return
97
+ end
98
+
93
99
  warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
94
100
  exit 42
95
101
  end
@@ -104,6 +110,4 @@ end
104
110
 
105
111
  m.load_bundler!
106
112
 
107
- if m.invoked_as_script?
108
- load Gem.bin_path("bundler", "bundle")
109
- end
113
+ load Gem.bin_path("bundler", "bundle") if m.invoked_as_script?
@@ -26,7 +26,7 @@ module SampleApp
26
26
  # Please, add to the `ignore` list any other `lib` subdirectories that do
27
27
  # not contain `.rb` files, or that should not be reloaded or eager loaded.
28
28
  # Common ones are `templates`, `generators`, or `middleware`, for example.
29
- config.autoload_lib(ignore: %w(assets tasks))
29
+ config.autoload_lib(ignore: %w[assets tasks])
30
30
 
31
31
  # Configuration for the application, engines, and railties goes here.
32
32
  #
@@ -45,11 +45,11 @@ Rails.application.configure do
45
45
 
46
46
  # Log to STDOUT by default
47
47
  config.logger = ActiveSupport::Logger.new(STDOUT)
48
- .tap { |logger| logger.formatter = ::Logger::Formatter.new }
49
- .then { |logger| ActiveSupport::TaggedLogging.new(logger) }
48
+ .tap { |logger| logger.formatter = ::Logger::Formatter.new }
49
+ .then { |logger| ActiveSupport::TaggedLogging.new(logger) }
50
50
 
51
51
  # Prepend all log lines with the following tags.
52
- config.log_tags = [ :request_id ]
52
+ config.log_tags = [:request_id]
53
53
 
54
54
  # Info include generic and useful information about system operation, but avoids logging too much
55
55
  # information to avoid inadvertent exposure of personally identifiable information (PII). If you
@@ -3,6 +3,6 @@
3
3
  # Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file.
4
4
  # Use this to limit dissemination of sensitive information.
5
5
  # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
6
- Rails.application.config.filter_parameters += [
7
- :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
6
+ Rails.application.config.filter_parameters += %i[
7
+ passw secret token _key crypt salt certificate otp ssn
8
8
  ]
@@ -2,7 +2,7 @@
2
2
 
3
3
  class InstallSnapcher < ActiveRecord::Migration[7.1]
4
4
  def self.up
5
- create_table :scannings, :force => true do |t|
5
+ create_table :scannings, force: true do |t|
6
6
  t.column :scannable_id, :integer
7
7
  t.column :scannable_type, :string
8
8
  t.column :table_name, :string
@@ -33,5 +33,4 @@ ActiveRecord::Schema[7.1].define(version: 2023_10_19_151334) do
33
33
  t.datetime "created_at", null: false
34
34
  t.datetime "updated_at", null: false
35
35
  end
36
-
37
36
  end
metadata CHANGED
@@ -1,16 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snapcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ryosk7
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-19 00:00:00.000000000 Z
11
+ date: 2023-10-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Save snapshot of DB columns.
13
+ description: |
14
+ Snapcher is an ORM extension that logs changes to specific columns to your model.
15
+ When a change is made to a specific column, the difference between before and after the change is obtained and saved.
16
+ To make it easier for analysts, save the table name, column name, and data before and after changes as separate columns.
14
17
  email:
15
18
  - uchiryo7@gmail.com
16
19
  executables: []
@@ -19,6 +22,7 @@ extra_rdoc_files: []
19
22
  files:
20
23
  - ".rspec"
21
24
  - ".rubocop.yml"
25
+ - ".rubocop_todo.yml"
22
26
  - ".ruby-version"
23
27
  - CHANGELOG.md
24
28
  - CODE_OF_CONDUCT.md
@@ -35,6 +39,7 @@ files:
35
39
  - lib/snapcher/scanning.rb
36
40
  - lib/snapcher/sweeper.rb
37
41
  - lib/snapcher/version.rb
42
+ - logo/snapcher_logo.png
38
43
  - sample-app/.dockerignore
39
44
  - sample-app/.gitattributes
40
45
  - sample-app/.gitignore
@@ -111,7 +116,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
116
  requirements:
112
117
  - - ">="
113
118
  - !ruby/object:Gem::Version
114
- version: 2.6.0
119
+ version: 3.1.0
115
120
  required_rubygems_version: !ruby/object:Gem::Requirement
116
121
  requirements:
117
122
  - - ">="
@@ -121,5 +126,6 @@ requirements: []
121
126
  rubygems_version: 3.4.10
122
127
  signing_key:
123
128
  specification_version: 4
124
- summary: Save snapshot of DB columns.
129
+ summary: Snapcher is an ORM extension that logs changes to specific columns to your
130
+ model.
125
131
  test_files: []