immosquare-active-record-change-tracker 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 299d11653d5c906ae788ed7b915a9b5570c056cdb7e43d16ae7e3bbeafab857e
4
+ data.tar.gz: 9bc986bd135035ec0e9708a7bef80e678c8b69f764b5781644e9a8c9c98f87b8
5
+ SHA512:
6
+ metadata.gz: 99002bc0bc01c7d4cafff14310e5942c00298ee8d3781414cd13d6f17fa8a53e8b84c98ca13a78a4c123a7f9a06a7f61396f9337cefea5fa026391b3e5c6721e
7
+ data.tar.gz: b24bca711330f70cb77f59d6929bdc87de2244f655f9e548e87c993a12dde6b05235b7da115be1acdec940cce11aa46195662531f3c6e8c32a29e5f6e0d912b7
@@ -0,0 +1,36 @@
1
+ require "rails/generators"
2
+ require "rails/generators/migration"
3
+
4
+
5
+ module ImmosquareActiveRecordChangeTracker
6
+ class InstallGenerator < Rails::Generators::Base
7
+
8
+ include Rails::Generators::Migration
9
+
10
+ source_root File.expand_path("templates", __dir__)
11
+
12
+ desc "Generate migration for Table ActiveRecordChangeTracker"
13
+
14
+ def copy_migration
15
+ migration_template("template_1.rb", "db/migrate/#{migration_name.underscore}.rb", :migration_version => migration_version)
16
+ end
17
+
18
+ def self.next_migration_number(dirname)
19
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
20
+ end
21
+
22
+ private
23
+
24
+
25
+ def migration_name
26
+ "CreateActiveRecordChangeTracker"
27
+ end
28
+
29
+ def migration_version
30
+ return if ActiveRecord::VERSION::MAJOR < 6
31
+
32
+ "[#{ActiveRecord::VERSION::STRING.to_f}]"
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,16 @@
1
+ class <%= "#{migration_name} < ActiveRecord::Migration#{migration_version}" %>
2
+
3
+ def change
4
+ create_table(:active_record_change_trackers) do |t|
5
+ t.references(:recordable, :polymorphic => true, :foreign_key => false, :index => false, :null => false)
6
+ t.references(:modifier, :polymorphic => true, :foreign_key => false, :index => false, :null => true)
7
+ t.string(:event, :null => true, :limit => 10)
8
+ t.text(:data, :null => true, :limit => 4_294_967_295)
9
+ t.datetime(:created_at, :null => false)
10
+ end
11
+
12
+ add_index(:active_record_change_trackers, [:recordable_type, :recordable_id])
13
+ add_index(:active_record_change_trackers, [:modifier_type, :modifier_id])
14
+ end
15
+
16
+ end
@@ -0,0 +1,15 @@
1
+ module ImmosquareActiveRecordChangeTracker
2
+ ##============================================================##
3
+ ## On nome le modèle différemment que ApplicationRecordHistory
4
+ ## pour éviter les conflits avec le nom du module.
5
+ ##============================================================##
6
+ class HistoryRecord < ::ActiveRecord::Base
7
+
8
+ self.table_name = "active_record_change_trackers"
9
+
10
+ belongs_to :recordable, :polymorphic => true
11
+ belongs_to :modifier, :polymorphic => true
12
+ serialize :data, :coder => JSON
13
+
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ require "rails"
2
+
3
+ module ImmosquareActiveRecordChangeTracker
4
+ class Railtie < Rails::Railtie
5
+
6
+ initializer "immosquare_active_record_change_tracker.active_record" do
7
+ ActiveSupport.on_load(:active_record) do
8
+ ##============================================================##
9
+ ## Pour ajouter une gestion de l'historique des modifications
10
+ ##============================================================##
11
+ extend ImmosquareActiveRecordChangeTracker::ClassMethods
12
+
13
+ ##============================================================##
14
+ ## Définir la classe HistoryRecord après le chargement d'ActiveRecord
15
+ ##============================================================##
16
+ require "immosquare-active-record-change-tracker/models/history_record"
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module ImmosquareActiveRecordChangeTracker
2
+ VERSION = "0.1.0".freeze
3
+ end
@@ -0,0 +1,136 @@
1
+ ##============================================================##
2
+ ## Rails
3
+ ##============================================================##
4
+ require_relative "immosquare-active-record-change-tracker/railtie"
5
+ require_relative "generators/immosquare-active-record-change-tracker/install/install_generator"
6
+
7
+
8
+ module ImmosquareActiveRecordChangeTracker
9
+ extend ActiveSupport::Concern
10
+
11
+ module ClassMethods
12
+ def track_active_record_changes(options = {}, &modifier_block)
13
+ ##============================================================##
14
+ ## Inclut les méthodes d'instance nécessaires
15
+ ##============================================================##
16
+ include(ImmosquareActiveRecordChangeTracker::InstanceMethods)
17
+
18
+ ##============================================================##
19
+ ## Stocker les options dans un attribut de classe
20
+ ##============================================================##
21
+ class_attribute(:history_options)
22
+ self.history_options = options
23
+
24
+ ##============================================================##
25
+ ## Stocker le bloc du modificateur s'il est fourni
26
+ ##============================================================##
27
+ history_options[:modifier_block] = modifier_block if block_given?
28
+
29
+ ##============================================================##
30
+ ## Configure le callback after_save
31
+ ##============================================================##
32
+ after_save(:save_change_history)
33
+ after_destroy(:delete_change_history)
34
+ end
35
+ end
36
+
37
+ module InstanceMethods
38
+ private
39
+
40
+ ##============================================================##
41
+ ## Stocker les changements après un create ou save ou update
42
+ ##============================================================##
43
+ def save_change_history
44
+ history_options = self.class.history_options
45
+
46
+ ##============================================================##
47
+ ## Récupérer les champs à observer
48
+ ##============================================================##
49
+ changes_to_save =
50
+ if history_options[:only].present?
51
+ previous_changes.slice(*history_options[:only].map(&:to_s))
52
+ else
53
+ excluded_fields = history_options[:except] || []
54
+ excluded_fields += [:created_at, :updated_at]
55
+ previous_changes.except(*excluded_fields.uniq.map(&:to_s))
56
+ end
57
+
58
+
59
+ ##============================================================##
60
+ ## Gestion de Globalize
61
+ ##============================================================##
62
+ if respond_to?(:translated_attribute_names)
63
+ translated_attribute_names = send(:translated_attribute_names).map(&:to_sym)
64
+ globalize_changes = {}
65
+
66
+ translations.each do |translation|
67
+ locale = translation.locale.to_sym
68
+ translation.previous_changes.each do |attribute, values|
69
+ attribute = attribute.to_sym
70
+ next if !attribute.in?(translated_attribute_names)
71
+
72
+ old_value, new_value = values
73
+ ##============================================================##
74
+ ## On ne sauvegarde pas les changements si les valeurs sont identiques
75
+ ## ou si on passe de nil à "" ou de "" à nil
76
+ ##============================================================##
77
+ next if old_value == new_value || (old_value.blank? && new_value.blank?)
78
+
79
+ globalize_changes[attribute] ||= {}
80
+ globalize_changes[attribute][locale] = [old_value, new_value]
81
+ end
82
+ end
83
+ changes_to_save.merge!(globalize_changes)
84
+ end
85
+
86
+
87
+ ##============================================================##
88
+ ## Si aucun changement à sauvegarder, on sort
89
+ ##============================================================##
90
+ return if changes_to_save.none?
91
+
92
+ ##============================================================##
93
+ ## Récupéreration du modificateur en exécutant le bloc s'il est défini
94
+ ##============================================================##
95
+ modifier = history_options[:modifier_block]&.call
96
+
97
+ ##============================================================##
98
+ ## Gestion de l'event
99
+ ##============================================================##
100
+ event = previously_new_record? ? "create" : "update"
101
+
102
+ ##============================================================##
103
+ ## On crée un enregistrement dans la table d'historique
104
+ ##============================================================##
105
+ ImmosquareActiveRecordChangeTracker::HistoryRecord.create!(
106
+ :recordable => self,
107
+ :modifier => modifier,
108
+ :data => changes_to_save,
109
+ :event => event,
110
+ :created_at => DateTime.now
111
+ )
112
+ end
113
+
114
+ ##============================================================##
115
+ ## Stocker l'évenement destroy
116
+ ## Pas besoin de data, rien n'a changé.
117
+ ##============================================================##
118
+ def delete_change_history
119
+ ##============================================================##
120
+ ## Récupéreration du modificateur en exécutant le bloc s'il est défini
121
+ ##============================================================##
122
+ modifier = history_options[:modifier_block]&.call
123
+
124
+ ##============================================================##
125
+ ## On crée un enregistrement dans la table d'historique
126
+ ##============================================================##
127
+ ImmosquareActiveRecordChangeTracker::HistoryRecord.create!(
128
+ :recordable => self,
129
+ :modifier => modifier,
130
+ :data => nil,
131
+ :event => "destroy",
132
+ :created_at => DateTime.now
133
+ )
134
+ end
135
+ end
136
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: immosquare-active-record-change-tracker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - IMMO SQUARE
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-10-01 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A gem to track changes on ActiveRecord models
14
+ email:
15
+ - jules@immosquare.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/generators/immosquare-active-record-change-tracker/install/install_generator.rb
21
+ - lib/generators/immosquare-active-record-change-tracker/install/templates/template_1.rb
22
+ - lib/immosquare-active-record-change-tracker.rb
23
+ - lib/immosquare-active-record-change-tracker/models/history_record.rb
24
+ - lib/immosquare-active-record-change-tracker/railtie.rb
25
+ - lib/immosquare-active-record-change-tracker/version.rb
26
+ homepage: https://github.com/IMMOSQUARE/immosquare-active-record-change-tracker
27
+ licenses:
28
+ - MIT
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: 2.7.2
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubygems_version: 3.5.11
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: ActiveRecord Change Tracker
49
+ test_files: []