rich-acts_as_revisable 0.6.0 → 0.9.8
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.
- data/LICENSE +1 -1
- data/{README → README.rdoc} +54 -25
- data/Rakefile +44 -0
- data/lib/acts_as_revisable/acts/common.rb +170 -23
- data/lib/acts_as_revisable/acts/deletable.rb +29 -0
- data/lib/acts_as_revisable/acts/revisable.rb +362 -127
- data/lib/acts_as_revisable/acts/revision.rb +94 -21
- data/lib/acts_as_revisable/acts/scoped_model.rb +28 -4
- data/lib/acts_as_revisable/base.rb +6 -3
- data/lib/acts_as_revisable/clone_associations.rb +8 -0
- data/lib/acts_as_revisable/gem_spec_options.rb +18 -0
- data/lib/acts_as_revisable/quoted_columns.rb +14 -9
- data/lib/acts_as_revisable/version.rb +2 -2
- data/spec/associations_spec.rb +22 -0
- data/spec/branch_spec.rb +42 -0
- data/spec/find_spec.rb +38 -0
- data/spec/{acts_as_revisable_spec.rb → general_spec.rb} +21 -26
- data/spec/quoted_columns_spec.rb +19 -0
- data/spec/revert_spec.rb +42 -0
- data/spec/spec_helper.rb +41 -5
- metadata +29 -16
- /data/spec/{aar_options_spec.rb → options_spec.rb} +0 -0
@@ -1,113 +1,120 @@
|
|
1
1
|
module FatJam
|
2
2
|
module ActsAsRevisable
|
3
|
+
|
4
|
+
# This module is mixed into the revision classes.
|
5
|
+
#
|
6
|
+
# ==== Callbacks
|
7
|
+
#
|
8
|
+
# * +before_revise+ is called before the record is revised.
|
9
|
+
# * +after_revise+ is called after the record is revised.
|
10
|
+
# * +before_revert+ is called before the record is reverted.
|
11
|
+
# * +after_revert+ is called after the record is reverted.
|
12
|
+
# * +before_changeset+ is called before a changeset block is called.
|
13
|
+
# * +after_changeset+ is called after a changeset block is called.
|
14
|
+
# * +after_branch_created+ is called on the new revisable instance
|
15
|
+
# created by branching after it's been created.
|
3
16
|
module Revisable
|
4
|
-
def self.included(base)
|
17
|
+
def self.included(base) #:nodoc:
|
5
18
|
base.send(:extend, ClassMethods)
|
6
|
-
|
7
|
-
base.class_inheritable_hash :aa_revisable_current_revisions
|
8
|
-
base.aa_revisable_current_revisions = {}
|
9
|
-
|
19
|
+
|
10
20
|
class << base
|
11
21
|
alias_method_chain :find, :revisable
|
12
22
|
alias_method_chain :with_scope, :revisable
|
23
|
+
attr_accessor :revisable_revision_class, :revisable_columns
|
13
24
|
end
|
14
|
-
|
25
|
+
|
26
|
+
base.class_inheritable_hash :revisable_shared_objects
|
27
|
+
base.revisable_shared_objects = {}
|
28
|
+
|
15
29
|
base.instance_eval do
|
30
|
+
attr_accessor :revisable_new_params, :revisable_revision
|
31
|
+
|
16
32
|
define_callbacks :before_revise, :after_revise, :before_revert, :after_revert, :before_changeset, :after_changeset, :after_branch_created
|
17
|
-
|
33
|
+
|
18
34
|
alias_method_chain :save, :revisable
|
19
35
|
alias_method_chain :save!, :revisable
|
20
|
-
|
21
|
-
acts_as_scoped_model :find => {:conditions => {:revisable_is_current => true}}
|
22
|
-
|
23
|
-
has_many :revisions, :class_name => revision_class_name, :foreign_key => :revisable_original_id, :order => "revisable_number DESC", :dependent => :destroy
|
24
|
-
has_many revision_class_name.pluralize.downcase.to_sym, :class_name => revision_class_name, :foreign_key => :revisable_original_id, :order => "revisable_number DESC", :dependent => :destroy
|
25
36
|
|
26
37
|
before_create :before_revisable_create
|
27
38
|
before_update :before_revisable_update
|
28
39
|
after_update :after_revisable_update
|
40
|
+
after_save :clear_revisable_shared_objects!, :unless => :is_reverting?
|
41
|
+
|
42
|
+
acts_as_scoped_model :find => {:conditions => {:revisable_is_current => true}}
|
43
|
+
|
44
|
+
[:revisions, revisions_association_name.to_sym].each do |assoc|
|
45
|
+
has_many assoc, (revisable_options.revision_association_options || {}).merge({:class_name => revision_class_name, :foreign_key => :revisable_original_id, :order => "#{quoted_table_name}.#{connection.quote_column_name(:revisable_number)} DESC", :dependent => :destroy})
|
46
|
+
end
|
29
47
|
end
|
30
48
|
end
|
31
|
-
|
32
|
-
def before_revisable_create
|
33
|
-
self[:revisable_is_current] = true
|
34
|
-
end
|
35
|
-
|
36
|
-
def should_revise?
|
37
|
-
return true if @aa_revisable_force_revision == true
|
38
|
-
return false if @aa_revisable_no_revision == true
|
39
|
-
return false unless self.changed?
|
40
|
-
!(self.changed.map(&:downcase) & self.class.revisable_columns).blank?
|
41
|
-
end
|
42
|
-
|
43
|
-
def before_revisable_update
|
44
|
-
return unless should_revise?
|
45
|
-
return false unless run_callbacks(:before_revise) { |r, o| r == false}
|
46
|
-
|
47
|
-
@revisable_revision = self.to_revision
|
48
|
-
end
|
49
|
-
|
50
|
-
def after_revisable_update
|
51
|
-
if @revisable_revision
|
52
|
-
@revisable_revision.save
|
53
|
-
@aa_revisable_was_revised = true
|
54
|
-
revisions.reload
|
55
|
-
run_callbacks(:after_revise)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def to_revision
|
60
|
-
rev = self.class.revision_class.new(@aa_revisable_new_params)
|
61
49
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
def find_revision(number)
|
88
|
-
revisions.find_by_revisable_number(number)
|
89
|
-
end
|
90
|
-
|
91
|
-
def revert_to!(*args)
|
92
|
-
unless run_callbacks(:before_revert) { |r, o| r == false}
|
93
|
-
raise ActiveRecord::RecordNotSaved
|
94
|
-
end
|
95
|
-
|
96
|
-
options = args.extract_options!
|
97
|
-
|
98
|
-
rev = case args.first
|
50
|
+
# Finds a specific revision of self.
|
51
|
+
#
|
52
|
+
# The +by+ parameter can be a revision_class instance,
|
53
|
+
# the symbols :first, :previous or :last, a Time instance
|
54
|
+
# or an Integer.
|
55
|
+
#
|
56
|
+
# When passed a revision_class instance, this method
|
57
|
+
# simply returns it. This is used primarily by revert_to!.
|
58
|
+
#
|
59
|
+
# When passed :first it returns the first revision created.
|
60
|
+
#
|
61
|
+
# When passed :previous or :last it returns the last revision
|
62
|
+
# created.
|
63
|
+
#
|
64
|
+
# When passed a Time instance it returns the revision that
|
65
|
+
# was the current record at the given time.
|
66
|
+
#
|
67
|
+
# When passed an Integer it returns the revision with that
|
68
|
+
# revision_number.
|
69
|
+
def find_revision(by)
|
70
|
+
by = Integer(by) if by.is_a?(String) && by.match(/[0-9]+/)
|
71
|
+
|
72
|
+
case by
|
73
|
+
when self.class
|
74
|
+
by
|
99
75
|
when self.class.revision_class
|
100
|
-
|
76
|
+
by
|
101
77
|
when :first
|
102
78
|
revisions.last
|
103
79
|
when :previous
|
104
80
|
revisions.first
|
105
|
-
when Fixnum
|
106
|
-
revisions.find_by_revisable_number(args.first)
|
107
81
|
when Time
|
108
|
-
revisions.find(:first, :conditions => ["? >= ? and ? <= ?", :revisable_revised_at,
|
82
|
+
revisions.find(:first, :conditions => ["? >= ? and ? <= ?", :revisable_revised_at, by, :revisable_current_at, by])
|
83
|
+
when self[:revisable_number]
|
84
|
+
self
|
85
|
+
else
|
86
|
+
revisions.find_by_revisable_number(by)
|
109
87
|
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns a revisable_class instance initialized with the record
|
91
|
+
# found using find_revision.
|
92
|
+
#
|
93
|
+
# The +what+ parameter is simply passed to find_revision and the
|
94
|
+
# returned record forms the basis of the reverted record.
|
95
|
+
#
|
96
|
+
# ==== Callbacks
|
97
|
+
#
|
98
|
+
# * +before_revert+ is called before the record is reverted.
|
99
|
+
# * +after_revert+ is called after the record is reverted.
|
100
|
+
#
|
101
|
+
# If :without_revision => true has not been passed the
|
102
|
+
# following callbacks are also called:
|
103
|
+
#
|
104
|
+
# * +before_revise+ is called before the record is revised.
|
105
|
+
# * +after_revise+ is called after the record is revised.
|
106
|
+
def revert_to(what, *args, &block) #:yields:
|
107
|
+
is_reverting!
|
108
|
+
|
109
|
+
unless run_callbacks(:before_revert) { |r, o| r == false}
|
110
|
+
raise ActiveRecord::RecordNotSaved
|
111
|
+
end
|
112
|
+
|
113
|
+
options = args.extract_options!
|
110
114
|
|
115
|
+
rev = find_revision(what)
|
116
|
+
self.reverting_to, self.reverting_from = rev, self
|
117
|
+
|
111
118
|
unless rev.run_callbacks(:before_restore) { |r, o| r == false}
|
112
119
|
raise ActiveRecord::RecordNotSaved
|
113
120
|
end
|
@@ -117,49 +124,112 @@ module FatJam
|
|
117
124
|
self[col] = rev[col]
|
118
125
|
end
|
119
126
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
+
self.no_revision! if options.delete :without_revision
|
128
|
+
self.revisable_new_params = options
|
129
|
+
|
130
|
+
yield(self) if block_given?
|
131
|
+
rev.run_callbacks(:after_restore)
|
132
|
+
run_callbacks(:after_revert)
|
133
|
+
self
|
134
|
+
ensure
|
135
|
+
is_reverting!(false)
|
136
|
+
clear_revisable_shared_objects!
|
127
137
|
end
|
128
138
|
|
139
|
+
# Same as revert_to except it also saves the record.
|
140
|
+
def revert_to!(what, *args)
|
141
|
+
revert_to(what, *args) do
|
142
|
+
self.no_revision? ? save! : revise!
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Equivalent to:
|
147
|
+
# revert_to(:without_revision => true)
|
148
|
+
def revert_to_without_revision(*args)
|
149
|
+
options = args.extract_options!
|
150
|
+
options.update({:without_revision => true})
|
151
|
+
revert_to(*(args << options))
|
152
|
+
end
|
153
|
+
|
154
|
+
# Equivalent to:
|
155
|
+
# revert_to!(:without_revision => true)
|
129
156
|
def revert_to_without_revision!(*args)
|
130
157
|
options = args.extract_options!
|
131
158
|
options.update({:without_revision => true})
|
132
159
|
revert_to!(*(args << options))
|
133
160
|
end
|
134
|
-
|
161
|
+
|
162
|
+
# Globally sets the reverting state of this record.
|
163
|
+
def is_reverting!(val=true) #:nodoc:
|
164
|
+
set_revisable_state(:reverting, val)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Returns true if the _record_ (not just this instance
|
168
|
+
# of the record) is currently being reverted.
|
169
|
+
def is_reverting?
|
170
|
+
get_revisable_state(:reverting) || false
|
171
|
+
end
|
172
|
+
|
173
|
+
# Sets whether or not to force a revision.
|
174
|
+
def force_revision!(val=true) #:nodoc:
|
175
|
+
set_revisable_state(:force_revision, val)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Returns true if a revision should be forced.
|
179
|
+
def force_revision? #:nodoc:
|
180
|
+
get_revisable_state(:force_revision) || false
|
181
|
+
end
|
182
|
+
|
183
|
+
# Sets whether or not a revision should be created.
|
184
|
+
def no_revision!(val=true) #:nodoc:
|
185
|
+
set_revisable_state(:no_revision, val)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Returns true if no revision should be created.
|
189
|
+
def no_revision? #:nodoc:
|
190
|
+
get_revisable_state(:no_revision) || false
|
191
|
+
end
|
192
|
+
|
193
|
+
# Force an immediate revision whether or
|
194
|
+
# not any columns have been modified.
|
195
|
+
#
|
196
|
+
# ==== Callbacks
|
197
|
+
#
|
198
|
+
# * +before_revise+ is called before the record is revised.
|
199
|
+
# * +after_revise+ is called after the record is revised.
|
135
200
|
def revise!
|
136
201
|
return if in_revision?
|
137
202
|
|
138
203
|
begin
|
139
|
-
|
204
|
+
force_revision!
|
140
205
|
in_revision!
|
141
206
|
save!
|
142
207
|
ensure
|
143
208
|
in_revision!(false)
|
144
|
-
|
209
|
+
force_revision!(false)
|
145
210
|
end
|
146
211
|
end
|
147
|
-
|
148
|
-
def revised?
|
149
|
-
@aa_revisable_was_revised || false
|
150
|
-
end
|
151
|
-
|
152
|
-
def in_revision?
|
153
|
-
key = self.read_attribute(self.class.primary_key)
|
154
|
-
aa_revisable_current_revisions[key] || false
|
155
|
-
end
|
156
|
-
|
157
|
-
def in_revision!(val=true)
|
158
|
-
key = self.read_attribute(self.class.primary_key)
|
159
|
-
aa_revisable_current_revisions[key] = val
|
160
|
-
aa_revisable_current_revisions.delete(key) unless val
|
161
|
-
end
|
162
212
|
|
213
|
+
# Groups statements that could trigger several revisions into
|
214
|
+
# a single revision. The revision is created once #save is called.
|
215
|
+
#
|
216
|
+
# ==== Example
|
217
|
+
#
|
218
|
+
# @project.revision_number # => 1
|
219
|
+
# @project.changeset do |project|
|
220
|
+
# # each one of the following statements would
|
221
|
+
# # normally trigger a revision
|
222
|
+
# project.update_attribute(:name, "new name")
|
223
|
+
# project.revise!
|
224
|
+
# project.revise!
|
225
|
+
# end
|
226
|
+
# @project.save
|
227
|
+
# @project.revision_number # => 2
|
228
|
+
#
|
229
|
+
# ==== Callbacks
|
230
|
+
#
|
231
|
+
# * +before_changeset+ is called before a changeset block is called.
|
232
|
+
# * +after_changeset+ is called after a changeset block is called.
|
163
233
|
def changeset(&block)
|
164
234
|
return unless block_given?
|
165
235
|
|
@@ -170,24 +240,169 @@ module FatJam
|
|
170
240
|
end
|
171
241
|
|
172
242
|
begin
|
243
|
+
force_revision!
|
173
244
|
in_revision!
|
174
245
|
|
175
246
|
returning(yield(self)) do
|
176
247
|
run_callbacks(:after_changeset)
|
177
248
|
end
|
178
249
|
ensure
|
179
|
-
in_revision!(false)
|
250
|
+
in_revision!(false)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
# Same as +changeset+ except it also saves the record.
|
255
|
+
def changeset!(&block)
|
256
|
+
changeset do
|
257
|
+
block.call(self)
|
258
|
+
save!
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def without_revisions!
|
263
|
+
return if in_revision? || !block_given?
|
264
|
+
|
265
|
+
begin
|
266
|
+
no_revision!
|
267
|
+
in_revision!
|
268
|
+
yield
|
269
|
+
save!
|
270
|
+
ensure
|
271
|
+
in_revision!(false)
|
272
|
+
no_revision!(false)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# acts_as_revisable's override for ActiveRecord::Base's #save!
|
277
|
+
def save_with_revisable!(*args) #:nodoc:
|
278
|
+
self.revisable_new_params ||= args.extract_options!
|
279
|
+
self.no_revision! if self.revisable_new_params.delete :without_revision
|
280
|
+
save_without_revisable!
|
281
|
+
end
|
282
|
+
|
283
|
+
# acts_as_revisable's override for ActiveRecord::Base's #save
|
284
|
+
def save_with_revisable(*args) #:nodoc:
|
285
|
+
self.revisable_new_params ||= args.extract_options!
|
286
|
+
self.no_revision! if self.revisable_new_params.delete :without_revision
|
287
|
+
save_without_revisable(args)
|
288
|
+
end
|
289
|
+
|
290
|
+
# Set some defaults for a newly created +Revisable+ instance.
|
291
|
+
def before_revisable_create #:nodoc:
|
292
|
+
self[:revisable_is_current] = true
|
293
|
+
self[:revisable_number] = 1
|
294
|
+
end
|
295
|
+
|
296
|
+
# Checks whether or not a +Revisable+ should be revised.
|
297
|
+
def should_revise? #:nodoc:
|
298
|
+
return false if new_record?
|
299
|
+
return true if force_revision?
|
300
|
+
return false if no_revision?
|
301
|
+
return false unless self.changed?
|
302
|
+
!(self.changed.map(&:downcase) & self.class.revisable_watch_columns).blank?
|
303
|
+
end
|
304
|
+
|
305
|
+
# Checks whether or not a revision should be stored.
|
306
|
+
# If it should be, it initialized the revision_class
|
307
|
+
# and stores it in an accessor for later saving.
|
308
|
+
def before_revisable_update #:nodoc:
|
309
|
+
return unless should_revise?
|
310
|
+
return false unless run_callbacks(:before_revise) { |r, o| r == false}
|
311
|
+
|
312
|
+
self.revisable_revision = self.to_revision
|
313
|
+
end
|
314
|
+
|
315
|
+
# Checks if an initialized revision_class has been stored
|
316
|
+
# in the accessor. If it has been, this instance is saved.
|
317
|
+
def after_revisable_update #:nodoc:
|
318
|
+
if no_revision? # check and see if no_revision! was called in a callback
|
319
|
+
self.revisable_revision = nil
|
320
|
+
return true
|
321
|
+
elsif self.revisable_revision
|
322
|
+
self.revisable_revision.save
|
323
|
+
revisions.reload
|
324
|
+
run_callbacks(:after_revise)
|
180
325
|
end
|
326
|
+
force_revision!(false)
|
327
|
+
true
|
181
328
|
end
|
182
329
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
330
|
+
# Returns true if the _record_ (not just this instance
|
331
|
+
# of the record) is currently being revised.
|
332
|
+
def in_revision?
|
333
|
+
get_revisable_state(:revision)
|
334
|
+
end
|
335
|
+
|
336
|
+
# Manages the internal state of a +Revisable+ controlling
|
337
|
+
# whether or not a record is being revised. This works across
|
338
|
+
# instances and is keyed on primary_key.
|
339
|
+
def in_revision!(val=true) #:nodoc:
|
340
|
+
set_revisable_state(:revision, val)
|
341
|
+
end
|
342
|
+
|
343
|
+
# This returns a new +Revision+ instance with all the appropriate
|
344
|
+
# values initialized.
|
345
|
+
def to_revision #:nodoc:
|
346
|
+
rev = self.class.revision_class.new(self.revisable_new_params)
|
347
|
+
|
348
|
+
rev.revisable_original_id = self.id
|
349
|
+
|
350
|
+
new_revision_number = revisions.maximum(:revisable_number) + 1 rescue self.revisable_number
|
351
|
+
rev.revisable_number = new_revision_number
|
352
|
+
self.revisable_number = new_revision_number + 1
|
353
|
+
|
354
|
+
self.class.column_names.each do |col|
|
355
|
+
next unless self.class.revisable_should_clone_column? col
|
356
|
+
val = self.send("#{col}_changed?") ? self.send("#{col}_was") : self.send(col)
|
357
|
+
rev.send("#{col}=", val)
|
358
|
+
end
|
359
|
+
|
360
|
+
self.revisable_new_params = nil
|
361
|
+
|
362
|
+
rev
|
187
363
|
end
|
188
364
|
|
189
|
-
|
190
|
-
|
365
|
+
# This returns
|
366
|
+
def current_revision
|
367
|
+
self
|
368
|
+
end
|
369
|
+
|
370
|
+
def for_revision
|
371
|
+
key = self.read_attribute(self.class.primary_key)
|
372
|
+
self.class.revisable_shared_objects[key] ||= {}
|
373
|
+
end
|
374
|
+
|
375
|
+
def reverting_to
|
376
|
+
for_revision[:reverting_to]
|
377
|
+
end
|
378
|
+
|
379
|
+
def reverting_to=(val)
|
380
|
+
for_revision[:reverting_to] = val
|
381
|
+
end
|
382
|
+
|
383
|
+
def reverting_from
|
384
|
+
for_revision[:reverting_from]
|
385
|
+
end
|
386
|
+
|
387
|
+
def reverting_from=(val)
|
388
|
+
for_revision[:reverting_from] = val
|
389
|
+
end
|
390
|
+
|
391
|
+
def clear_revisable_shared_objects!
|
392
|
+
key = self.read_attribute(self.class.primary_key)
|
393
|
+
self.class.revisable_shared_objects.delete(key)
|
394
|
+
end
|
395
|
+
|
396
|
+
module ClassMethods
|
397
|
+
# acts_as_revisable's override for with_scope that allows for
|
398
|
+
# including revisions in the scope.
|
399
|
+
#
|
400
|
+
# ==== Example
|
401
|
+
#
|
402
|
+
# with_scope(:with_revisions => true) do
|
403
|
+
# ...
|
404
|
+
# end
|
405
|
+
def with_scope_with_revisable(*args, &block) #:nodoc:
|
191
406
|
options = (args.grep(Hash).first || {})[:find]
|
192
407
|
|
193
408
|
if options && options.delete(:with_revisions)
|
@@ -198,8 +413,14 @@ module FatJam
|
|
198
413
|
with_scope_without_revisable(*args, &block)
|
199
414
|
end
|
200
415
|
end
|
201
|
-
|
202
|
-
|
416
|
+
|
417
|
+
# acts_as_revisable's override for find that allows for
|
418
|
+
# including revisions in the find.
|
419
|
+
#
|
420
|
+
# ==== Example
|
421
|
+
#
|
422
|
+
# find(:all, :with_revisions => true)
|
423
|
+
def find_with_revisable(*args) #:nodoc:
|
203
424
|
options = args.grep(Hash).first
|
204
425
|
|
205
426
|
if options && options.delete(:with_revisions)
|
@@ -210,36 +431,50 @@ module FatJam
|
|
210
431
|
find_without_revisable(*args)
|
211
432
|
end
|
212
433
|
end
|
213
|
-
|
434
|
+
|
435
|
+
# Equivalent to:
|
436
|
+
# find(..., :with_revisions => true)
|
214
437
|
def find_with_revisions(*args)
|
215
438
|
args << {} if args.grep(Hash).blank?
|
216
439
|
args.grep(Hash).first.update({:with_revisions => true})
|
217
440
|
find_with_revisable(*args)
|
218
441
|
end
|
219
442
|
|
220
|
-
|
443
|
+
# Returns the +revision_class_name+ as configured in
|
444
|
+
# +acts_as_revisable+.
|
445
|
+
def revision_class_name #:nodoc:
|
221
446
|
self.revisable_options.revision_class_name || "#{self.class_name}Revision"
|
222
447
|
end
|
223
448
|
|
224
|
-
|
225
|
-
|
449
|
+
# Returns the actual +Revision+ class based on the
|
450
|
+
# #revision_class_name.
|
451
|
+
def revision_class #:nodoc:
|
452
|
+
self.revisable_revision_class ||= revision_class_name.constantize
|
226
453
|
end
|
227
454
|
|
228
|
-
|
455
|
+
# Returns the revisable_class which in this case is simply +self+.
|
456
|
+
def revisable_class #:nodoc:
|
229
457
|
self
|
230
458
|
end
|
231
459
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
460
|
+
# Returns the name of the association acts_as_revisable
|
461
|
+
# creates.
|
462
|
+
def revisions_association_name #:nodoc:
|
463
|
+
revision_class_name.pluralize.downcase
|
464
|
+
end
|
465
|
+
|
466
|
+
# Returns an Array of the columns that are watched for changes.
|
467
|
+
def revisable_watch_columns #:nodoc:
|
468
|
+
return self.revisable_columns unless self.revisable_columns.blank?
|
469
|
+
return self.revisable_columns ||= [] if self.revisable_options.except == :all
|
470
|
+
return self.revisable_columns ||= [self.revisable_options.only].flatten.map(&:to_s).map(&:downcase) unless self.revisable_options.only.blank?
|
236
471
|
|
237
472
|
except = [self.revisable_options.except].flatten || []
|
238
473
|
except += REVISABLE_SYSTEM_COLUMNS
|
239
474
|
except += REVISABLE_UNREVISABLE_COLUMNS
|
240
475
|
except.uniq!
|
241
476
|
|
242
|
-
|
477
|
+
self.revisable_columns ||= (column_names - except.map(&:to_s)).flatten.map(&:downcase)
|
243
478
|
end
|
244
479
|
end
|
245
480
|
end
|