sequel-revisions 0.1.1 → 0.2.1

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sequel/plugins/revisions.rb +170 -61
  3. metadata +34 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b638d9cddc49884c2e02153531cb651e74e8f465
4
- data.tar.gz: 7f44a3fa58deb5145a6aef9bbd59e55ec02017ec
3
+ metadata.gz: 78b1a7fff0b37569c9483503d58542a6859878a0
4
+ data.tar.gz: abcc54a0f00e59827389312a65ffb359f3e2a64b
5
5
  SHA512:
6
- metadata.gz: 531a84641e345fc5270b0b2f81af0ca4b99a57882bd97dffb662773d49713aa1f1d423cc15b857405cf4dede7783f9ce1908501c51a0c43760e9edd3f1ea8af0
7
- data.tar.gz: 11bedd40539e7b727b4afc91980cfa0ed14b78cfe2917d3471e4eefcdd07e139715ec9ba80e1dd52602b0f4309eaf0c66c7b142dd24f06bf3a3f602692eb44a5
6
+ metadata.gz: 2bfd8bf7a0b2cdda5a17352d05703f821629ce039aabe3c573c648e13be490551f3dfb725315c9c36f27c2bd9edc255ff985f22f2855a4a627b150ed48f062c3
7
+ data.tar.gz: e7f8355ceb4db7b8450315a628a048f28866e5b1f71d8db3ef7772762643895fdef17bfabddf2d8f294b55016ced5131c9b38fb5a80c7fe4214c8c2b139f7677
@@ -1,93 +1,202 @@
1
1
  require 'sequel'
2
2
  require 'json'
3
3
 
4
- module Sequel::Plugins
5
- module Revisions
6
- def self.apply(model, options = {})
7
- options = {
8
- model_name: "#{model.name}Revisions",
9
- table_name: "#{model.table_name.to_s.singularize}_revisions",
10
- exclude: [:created_at, :updated_at],
11
- meta: nil
12
- }.merge(options)
13
-
14
- base_name = options[:model_name]
15
-
16
- mods = options[:model_name].split("::")
17
- if mods.length > 1
18
- mobject = Object.const_get mods[0..mods.length-2].join("::")
19
- base_name = mods.last
20
- else
21
- mobject = Object
4
+ module Sequel
5
+ module Plugins
6
+ module Revisions
7
+ def self.apply(model, options = {})
8
+ options = set_options(model, options)
9
+ model.class_eval do
10
+ @revisions_polymorphic = options[:polymorphic]
11
+ @revisions_embedded_in = options[:embedded_in]
12
+ @revisions_on = options[:on]
13
+ @revisions_meta = options[:meta]
14
+ @revisions_exclude = options[:exclude]
15
+ end
22
16
  end
23
17
 
24
- # Dynamically create Model class
25
- klass = Class.new(Sequel::Model(options[:table_name].to_sym))
26
- klass.class_eval do
27
- @@lmeta = options[:meta]
28
- plugin :timestamps
29
- plugin :serialization
18
+ def self.configure(model, options = {})
19
+ options = set_options(model, options)
30
20
 
31
- serialize_attributes :json, :meta
32
- serialize_attributes :json, :changes
33
- many_to_one model.table_name.to_sym, class: model.name
21
+ base_name = options[:model_name]
34
22
 
35
- def before_create
36
- # ToDo: This should not call to_json. Maybe a bug?
37
- self[:meta] = @@lmeta.call().to_json unless @@lmeta.nil?
38
- super
23
+ mods = options[:model_name].split("::")
24
+ if mods.length > 1
25
+ mobject = Object.const_get mods[0..mods.length-2].join("::")
26
+ base_name = mods.last
27
+ else
28
+ mobject = Object
29
+ end
30
+
31
+ # Don't redefine
32
+ unless mobject.const_defined?(base_name)
33
+ klass = setup_revisions_model(model, options)
34
+ # Actually define the class in the module
35
+ mobject.const_set base_name, klass
39
36
  end
37
+
38
+ # Configure associations / methods on models
39
+ setup_model(model, options)
40
40
  end
41
41
 
42
- # Actually define the class in the module
43
- mobject.const_set base_name, klass
42
+ module ClassMethods
43
+ Plugins.inherited_instance_variables(self,
44
+ :@revisions_polymorphic => :dup,
45
+ :@revisions_embedded_in => :dup,
46
+ :@revisions_on => :dup,
47
+ :@revisions_exclude => :dup,
48
+ :@revisions_meta => nil)
44
49
 
45
- model.class_eval do
46
- plugin :dirty
47
- one_to_many :revisions, class: options[:model_name]
50
+ def revisions_polymorphic?
51
+ @revisions_polymorphic
52
+ end
48
53
 
49
- def revert
50
- return if revisions.empty?
54
+ def revisions_embedded_in
55
+ @revisions_embedded_in
56
+ end
51
57
 
52
- last = revisions.last
53
- changes = last.changes
54
- changes.keys.each do |key|
55
- send("#{key}=", changes[key][0])
58
+ def revisions_on? action
59
+ # We track everything by default
60
+ unless @revisions_on
61
+ true
62
+ else
63
+ @revisions_on.include? action
56
64
  end
57
65
  end
58
66
 
59
- def revert!
60
- revert
61
- save
67
+ def revisions_meta
68
+ @revisions_meta
69
+ end
70
+
71
+ def revisions_exclude
72
+ @revisions_exclude
62
73
  end
63
74
  end
64
- end
65
75
 
66
- def self.configure(model, options = {})
67
- end
76
+ module InstanceMethods
68
77
 
69
- module ClassMethods
70
- end
78
+ def before_update
79
+ super
80
+ track_changes(:update) if model.revisions_on? :update
81
+ end
82
+
83
+ def before_destroy
84
+ super
85
+ track_changes(:destroy) if model.revisions_on? :destroy
86
+ end
87
+
88
+ def after_create
89
+ super
90
+ track_changes(:create) if model.revisions_on? :create
91
+ end
92
+
93
+ private
94
+
95
+ def track_changes(action)
96
+ case action
97
+ when :update
98
+ return if changed_columns.empty?
99
+ # Map the changed fields into an object
100
+ changes = changed_columns.inject({}) do |obj, key|
101
+ obj[key] = column_change(key)
102
+ obj
103
+ end
104
+ when :create
105
+ changes = (columns - model.revisions_exclude).inject({}) do |obj, key|
106
+ obj[key] = [nil, send(key)]
107
+ obj
108
+ end
109
+ when :destroy
110
+ changes = (columns - model.revisions_exclude).inject({}) do |obj, key|
111
+ obj[key] = [send(key), nil]
112
+ obj
113
+ end
114
+ end
71
115
 
72
- module InstanceMethods
116
+ #
117
+ meta = model.revisions_meta.call() unless model.revisions_meta.nil?
73
118
 
74
- def before_update
75
- track_changes
76
- super
119
+ if model.revisions_embedded_in.nil?
120
+ add_revision(changes: changes, action: action, meta: meta)
121
+ else
122
+ trackable = self.send(model.revisions_embedded_in)
123
+ add_revision(changes: changes, action: action, meta: meta, trackable: trackable)
124
+ end
125
+ end
77
126
  end
78
127
 
79
128
  private
80
129
 
81
- def track_changes
82
- return if changed_columns.empty?
130
+ def self.set_options(model, options)
131
+ model_name = options[:polymorphic] ? "Revision" : "#{model.name}Revision"
132
+ table_name = options[:polymorphic] ? "revisions" : "#{model.table_name.to_s.singularize}_revisions"
133
+
134
+ options = {
135
+ model_name: model_name,
136
+ table_name: table_name,
137
+ exclude: [:id, :created_at, :updated_at],
138
+ meta: nil
139
+ }.merge(options)
140
+ end
141
+
142
+ def self.setup_revisions_model(model, options)
143
+ # Dynamically create Model class
144
+ klass = Class.new(Sequel::Model(options[:table_name].to_sym))
145
+ klass.class_eval do
146
+ plugin :timestamps
147
+ plugin :serialization
148
+
149
+ serialize_attributes :json, :meta
150
+ serialize_attributes :json, :changes
151
+ end
152
+
153
+ if options[:polymorphic]
154
+ klass.class_eval do
155
+ many_to_one :trackable, polymorphic: true
156
+ many_to_one :embeddable, polymorphic: true
157
+ end
158
+ else
159
+ klass.class_eval do
160
+ many_to_one model.table_name.to_sym, class: model.name
161
+ end
162
+ end
163
+
164
+ klass
165
+ end
166
+
167
+ def self.setup_model(model, options)
168
+ model.class_eval do
169
+ plugin :dirty
170
+
171
+ def revert
172
+ return if revisions.empty?
173
+
174
+ last = revisions.last
175
+ changes = last.changes
176
+ changes.keys.each do |key|
177
+ send("#{key}=", changes[key][0])
178
+ end
179
+ end
83
180
 
84
- # Map the changed fields into an object
85
- changes = changed_columns.inject({}) do |obj, key|
86
- obj[key] = column_change(key)
87
- obj
181
+ def revert!
182
+ revert
183
+ save
184
+ end
88
185
  end
89
186
 
90
- add_revision(changes: changes)
187
+ if options[:polymorphic]
188
+ model.class_eval do
189
+ one_to_many :revisions, as: :trackable
190
+ end
191
+ elsif options[:embedded_in]
192
+ model.class_eval do
193
+ one_to_many :revisions, as: :embeddable
194
+ end
195
+ else
196
+ model.class_eval do
197
+ one_to_many :revisions, class: options[:model_name]
198
+ end
199
+ end
91
200
  end
92
201
  end
93
202
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel-revisions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fabian Becker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-19 00:00:00.000000000 Z
11
+ date: 2016-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -38,34 +38,62 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sequel_polymorphic
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: sqlite3
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '0'
61
+ version: '1'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '0'
68
+ version: '1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rspec
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
87
  - - "~>"
60
88
  - !ruby/object:Gem::Version
61
- version: '0'
89
+ version: '3'
62
90
  type: :development
63
91
  prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
94
  - - "~>"
67
95
  - !ruby/object:Gem::Version
68
- version: '0'
96
+ version: '3'
69
97
  description: Use this plugin to track field changes and revert your model to an older
70
98
  state.
71
99
  email: halfdan@xnorfz.de