Module: WithoutScope::ActsAsRevisable::Revisable
- Defined in:
- lib/acts_as_revisable/acts/revisable.rb
Overview
This module is mixed into the revision classes.
Callbacks
-
before_revise
is called before the record is revised. -
after_revise
is called after the record is revised. -
before_revert
is called before the record is reverted. -
after_revert
is called after the record is reverted. -
before_changeset
is called before a changeset block is called. -
after_changeset
is called after a changeset block is called. -
after_branch_created
is called on the new revisable instance created by branching after it’s been created.
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
-
.included(base) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#after_revisable_update ⇒ Object
Checks if an initialized revision_class has been stored in the accessor.
-
#before_revisable_create ⇒ Object
Set some defaults for a newly created
Revisable
instance. -
#before_revisable_update ⇒ Object
Checks whether or not a revision should be stored.
-
#changeset(&block) ⇒ Object
Groups statements that could trigger several revisions into a single revision.
-
#changeset!(&block) ⇒ Object
Same as
changeset
except it also saves the record. - #clear_revisable_shared_objects! ⇒ Object
-
#current_revision ⇒ Object
This returns.
-
#find_revision(by) ⇒ Object
Finds a specific revision of self.
- #for_revision ⇒ Object
-
#force_revision!(val = true) ⇒ Object
Sets whether or not to force a revision.
-
#force_revision? ⇒ Boolean
Returns true if a revision should be forced.
-
#in_revision!(val = true) ⇒ Object
Manages the internal state of a
Revisable
controlling whether or not a record is being revised. -
#in_revision? ⇒ Boolean
Returns true if the record (not just this instance of the record) is currently being revised.
-
#is_reverting!(val = true) ⇒ Object
Globally sets the reverting state of this record.
-
#is_reverting? ⇒ Boolean
Returns true if the record (not just this instance of the record) is currently being reverted.
-
#no_revision!(val = true) ⇒ Object
Sets whether or not a revision should be created.
-
#no_revision? ⇒ Boolean
Returns true if no revision should be created.
-
#revert_to(what, *args, &block) ⇒ Object
Returns a revisable_class instance initialized with the record found using find_revision.
-
#revert_to!(what, *args) ⇒ Object
Same as revert_to except it also saves the record.
-
#revert_to_without_revision(*args) ⇒ Object
Equivalent to: revert_to(:without_revision => true).
-
#revert_to_without_revision!(*args) ⇒ Object
Equivalent to: revert_to!(:without_revision => true).
- #reverting_from ⇒ Object
- #reverting_from=(val) ⇒ Object
- #reverting_to ⇒ Object
- #reverting_to=(val) ⇒ Object
-
#revise!(*args) ⇒ Object
Force an immediate revision whether or not any columns have been modified.
-
#save(*args) ⇒ Object
acts_as_revisable’s override for ActiveRecord::Base’s #save.
-
#save!(*args) ⇒ Object
acts_as_revisable’s override for ActiveRecord::Base’s #save!.
-
#should_revise? ⇒ Boolean
Checks whether or not a
Revisable
should be revised. -
#to_revision ⇒ Object
This returns a new
Revision
instance with all the appropriate values initialized. - #without_revisions! ⇒ Object
Class Method Details
.included(base) ⇒ Object
:nodoc:
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 17 def self.included(base) #:nodoc: base.send(:extend, ClassMethods) class << base attr_accessor :revisable_revision_class, :revisable_columns end base.class_inheritable_hash :revisable_shared_objects base.revisable_shared_objects = {} base.instance_eval do attr_accessor :revisable_new_params, :revisable_revision define_callbacks :before_revise, :after_revise, :before_revert, :after_revert, :before_changeset, :after_changeset, :after_branch_created before_create :before_revisable_create before_update :before_revisable_update after_update :after_revisable_update after_save :clear_revisable_shared_objects!, :unless => :is_reverting? default_scope :conditions => {:revisable_is_current => true} [:revisions, revisions_association_name.to_sym].each do |assoc| has_many assoc, (. || {}).merge({:class_name => revision_class_name, :foreign_key => :revisable_original_id, :order => "#{quoted_table_name}.#{connection.quote_column_name(:revisable_number)} DESC", :dependent => :destroy}) end end if !Object.const_defined?(base.revision_class_name) && base..generate_revision_class? Object.const_set(base.revision_class_name, Class.new(ActiveRecord::Base)).instance_eval do acts_as_revision end end end |
Instance Method Details
#after_revisable_update ⇒ Object
Checks if an initialized revision_class has been stored in the accessor. If it has been, this instance is saved.
327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 327 def after_revisable_update #:nodoc: if no_revision? # check and see if no_revision! was called in a callback self.revisable_revision = nil return true elsif self.revisable_revision self.revisable_revision.save revisions.reload run_callbacks(:after_revise) end in_revision!(false) force_revision!(false) true end |
#before_revisable_create ⇒ Object
Set some defaults for a newly created Revisable
instance.
296 297 298 299 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 296 def before_revisable_create #:nodoc: self[:revisable_is_current] = true self.revision_number ||= 0 end |
#before_revisable_update ⇒ Object
Checks whether or not a revision should be stored. If it should be, it initialized the revision_class and stores it in an accessor for later saving.
313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 313 def before_revisable_update #:nodoc: return unless should_revise? in_revision! unless run_callbacks(:before_revise) { |r, o| r == false} in_revision!(false) return false end self.revisable_revision = self.to_revision end |
#changeset(&block) ⇒ Object
Groups statements that could trigger several revisions into a single revision. The revision is created once #save is called.
Example
@project.revision_number # => 1
@project.changeset do |project|
# each one of the following statements would
# normally trigger a revision
project.update_attribute(:name, "new name")
project.revise!
project.revise!
end
@project.save
@project.revision_number # => 2
Callbacks
-
before_changeset
is called before a changeset block is called. -
after_changeset
is called after a changeset block is called.
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 238 def changeset(&block) return unless block_given? return yield(self) if in_revision? unless run_callbacks(:before_changeset) { |r, o| r == false} raise ActiveRecord::RecordNotSaved end begin force_revision! in_revision! returning(yield(self)) do run_callbacks(:after_changeset) end ensure in_revision!(false) end end |
#changeset!(&block) ⇒ Object
Same as changeset
except it also saves the record.
260 261 262 263 264 265 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 260 def changeset!(&block) changeset do block.call(self) save! end end |
#clear_revisable_shared_objects! ⇒ Object
402 403 404 405 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 402 def clear_revisable_shared_objects! key = self.read_attribute(self.class.primary_key) self.class.revisable_shared_objects.delete(key) end |
#current_revision ⇒ Object
This returns
377 378 379 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 377 def current_revision self end |
#find_revision(by) ⇒ Object
Finds a specific revision of self.
The by
parameter can be a revision_class instance, the symbols :first, :previous or :last, a Time instance or an Integer.
When passed a revision_class instance, this method simply returns it. This is used primarily by revert_to!.
When passed :first it returns the first revision created.
When passed :previous or :last it returns the last revision created.
When passed a Time instance it returns the revision that was the current record at the given time.
When passed an Integer it returns the revision with that revision_number.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 70 def find_revision(by) by = Integer(by) if by.is_a?(String) && by.match(/[0-9]+/) case by when self.class by when self.class.revision_class by when :first revisions.last when :previous, :last revisions.first when Time revisions.find(:first, :conditions => ["? >= ? and ? <= ?", :revisable_revised_at, by, :revisable_current_at, by]) when self.revisable_number self else revisions.find_by_revisable_number(by) end end |
#for_revision ⇒ Object
381 382 383 384 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 381 def for_revision key = self.read_attribute(self.class.primary_key) self.class.revisable_shared_objects[key] ||= {} end |
#force_revision!(val = true) ⇒ Object
Sets whether or not to force a revision.
175 176 177 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 175 def force_revision!(val=true) #:nodoc: set_revisable_state(:force_revision, val) end |
#force_revision? ⇒ Boolean
Returns true if a revision should be forced.
180 181 182 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 180 def force_revision? #:nodoc: get_revisable_state(:force_revision) || false end |
#in_revision!(val = true) ⇒ Object
Manages the internal state of a Revisable
controlling whether or not a record is being revised. This works across instances and is keyed on primary_key.
350 351 352 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 350 def in_revision!(val=true) #:nodoc: set_revisable_state(:revision, val) end |
#in_revision? ⇒ Boolean
Returns true if the record (not just this instance of the record) is currently being revised.
343 344 345 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 343 def in_revision? get_revisable_state(:revision) end |
#is_reverting!(val = true) ⇒ Object
Globally sets the reverting state of this record.
164 165 166 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 164 def is_reverting!(val=true) #:nodoc: set_revisable_state(:reverting, val) end |
#is_reverting? ⇒ Boolean
Returns true if the record (not just this instance of the record) is currently being reverted.
170 171 172 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 170 def is_reverting? get_revisable_state(:reverting) || false end |
#no_revision!(val = true) ⇒ Object
Sets whether or not a revision should be created.
185 186 187 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 185 def no_revision!(val=true) #:nodoc: set_revisable_state(:no_revision, val) end |
#no_revision? ⇒ Boolean
Returns true if no revision should be created.
190 191 192 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 190 def no_revision? #:nodoc: get_revisable_state(:no_revision) || false end |
#revert_to(what, *args, &block) ⇒ Object
Returns a revisable_class instance initialized with the record found using find_revision.
The what
parameter is simply passed to find_revision and the returned record forms the basis of the reverted record.
Callbacks
-
before_revert
is called before the record is reverted. -
after_revert
is called after the record is reverted.
If :without_revision => true has not been passed the following callbacks are also called:
-
before_revise
is called before the record is revised. -
after_revise
is called after the record is revised.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 107 def revert_to(what, *args, &block) #:yields: is_reverting! unless run_callbacks(:before_revert) { |r, o| r == false} raise ActiveRecord::RecordNotSaved end = args. rev = find_revision(what) self.reverting_to, self.reverting_from = rev, self unless rev.run_callbacks(:before_restore) { |r, o| r == false} raise ActiveRecord::RecordNotSaved end self.class.column_names.each do |col| next unless self.class.revisable_should_clone_column? col self[col] = rev[col] end self.no_revision! if .delete :without_revision self.revisable_new_params = yield(self) if block_given? rev.run_callbacks(:after_restore) run_callbacks(:after_revert) self ensure is_reverting!(false) clear_revisable_shared_objects! end |
#revert_to!(what, *args) ⇒ Object
Same as revert_to except it also saves the record.
141 142 143 144 145 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 141 def revert_to!(what, *args) revert_to(what, *args) do self.no_revision? ? save! : revise! end end |
#revert_to_without_revision(*args) ⇒ Object
Equivalent to:
revert_to(:without_revision => true)
149 150 151 152 153 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 149 def revert_to_without_revision(*args) = args. .update({:without_revision => true}) revert_to(*(args << )) end |
#revert_to_without_revision!(*args) ⇒ Object
Equivalent to:
revert_to!(:without_revision => true)
157 158 159 160 161 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 157 def revert_to_without_revision!(*args) = args. .update({:without_revision => true}) revert_to!(*(args << )) end |
#reverting_from ⇒ Object
394 395 396 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 394 def reverting_from for_revision[:reverting_from] end |
#reverting_from=(val) ⇒ Object
398 399 400 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 398 def reverting_from=(val) for_revision[:reverting_from] = val end |
#reverting_to ⇒ Object
386 387 388 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 386 def reverting_to for_revision[:reverting_to] end |
#reverting_to=(val) ⇒ Object
390 391 392 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 390 def reverting_to=(val) for_revision[:reverting_to] = val end |
#revise!(*args) ⇒ Object
Force an immediate revision whether or not any columns have been modified.
The args
catch-all argument is not used. It’s primarily there to allow revise!
to be used directly as an association callback since association callbacks are passed an argument.
Callbacks
-
before_revise
is called before the record is revised. -
after_revise
is called after the record is revised.
205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 205 def revise!(*args) return if in_revision? begin force_revision! in_revision! save! ensure in_revision!(false) force_revision!(false) end end |
#save(*args) ⇒ Object
acts_as_revisable’s override for ActiveRecord::Base’s #save
289 290 291 292 293 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 289 def save(*args) #:nodoc: self.revisable_new_params ||= args. self.no_revision! if self.revisable_new_params.delete :without_revision super(args) end |
#save!(*args) ⇒ Object
acts_as_revisable’s override for ActiveRecord::Base’s #save!
282 283 284 285 286 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 282 def save!(*args) #:nodoc: self.revisable_new_params ||= args. self.no_revision! if self.revisable_new_params.delete :without_revision super end |
#should_revise? ⇒ Boolean
Checks whether or not a Revisable
should be revised.
302 303 304 305 306 307 308 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 302 def should_revise? #:nodoc: return false if new_record? return true if force_revision? return false if no_revision? return false unless self.changed? !(self.changed.map(&:downcase) & self.class.revisable_watch_columns).blank? end |
#to_revision ⇒ Object
This returns a new Revision
instance with all the appropriate values initialized.
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 356 def to_revision #:nodoc: rev = self.class.revision_class.new(self.revisable_new_params) rev.revisable_original_id = self.id new_revision_number = revisions.maximum(:revisable_number) + 1 rescue self.revision_number rev.revision_number = new_revision_number self.revision_number = new_revision_number + 1 self.class.column_names.each do |col| next unless self.class.revisable_should_clone_column? col val = self.send("#{col}_changed?") ? self.send("#{col}_was") : self.send(col) rev.send("#{col}=", val) end self.revisable_new_params = nil rev end |
#without_revisions! ⇒ Object
267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/acts_as_revisable/acts/revisable.rb', line 267 def without_revisions! return if in_revision? || !block_given? begin no_revision! in_revision! yield save! ensure in_revision!(false) no_revision!(false) end end |