Module: Cms::Behaviors::Versioning::InstanceMethods
- Defined in:
- lib/cms/behaviors/versioning.rb
Instance Method Summary collapse
- #as_of_draft_version ⇒ Object
-
#as_of_version(version) ⇒ ContentBlock
Find a Content Block as of a specific version.
-
#build_new_version ⇒ Object
Build a new version of this record and associate it with this record.
- #build_new_version_and_add_to_versions_list_for_saving ⇒ Object
-
#create_or_update ⇒ Object
ActiveRecord 3.0.0 call chain ActiveRecord 3 now uses basic inheritence rather than alias_method_chain.
- #current_version ⇒ Object
- #default_version_comment ⇒ Object
- #different_from_last_draft? ⇒ Boolean
- #draft ⇒ Object
- #draft_attributes ⇒ Object
- #draft_version? ⇒ Boolean
- #find_version(number) ⇒ Object
- #initialize_version ⇒ Object
- #live_version ⇒ Object
- #live_version? ⇒ Boolean
- #publish_if_needed ⇒ Object
- #revert ⇒ Object
- #revert_to(version) ⇒ Object
- #revert_to_without_save(version) ⇒ Object
-
#save!(perform_validations = true) ⇒ Object
def save(perform_validations=true) transaction do #logger.info “.….
- #version_comment ⇒ Object
- #version_comment=(version_comment) ⇒ Object
Instance Method Details
#as_of_draft_version ⇒ Object
306 307 308 |
# File 'lib/cms/behaviors/versioning.rb', line 306 def as_of_draft_version as_of_version(draft.version) end |
#as_of_version(version) ⇒ ContentBlock
Find a Content Block as of a specific version.
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/cms/behaviors/versioning.rb', line 314 def as_of_version(version) v = find_version(version) raise ActiveRecord::RecordNotFound.new("version #{version.inspect} does not exist for <#{self.class}:#{id}>") unless v obj = self.class.new (self.class.versioned_columns + [:version, :created_at, :created_by_id, :updated_at, :updated_by_id]).each do |a| obj.send("#{a}=", v.send(a)) end obj.id = id obj.lock_version = lock_version # Need to do this so associations can be loaded obj.instance_variable_set("@persisted", true) obj.instance_variable_set("@new_record", false) # Callback to allow us to load other data when an older version is loaded obj.after_as_of_version if obj.respond_to?(:after_as_of_version) # Last but not least, clear the changed attributes if changed_attrs = obj.send(:changed_attributes) changed_attrs.clear end obj end |
#build_new_version ⇒ Object
Build a new version of this record and associate it with this record.
Called as a before_create in order to correctly allow any other associations to be saved correctly. Called explicitly during update, where it will just define the new_version to be saved.
199 200 201 202 |
# File 'lib/cms/behaviors/versioning.rb', line 199 def build_new_version @new_version = build_new_version_and_add_to_versions_list_for_saving logger.debug {"New version of #{self.class}::Version is #{@new_version.attributes}"} end |
#build_new_version_and_add_to_versions_list_for_saving ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/cms/behaviors/versioning.rb', line 105 def build_new_version_and_add_to_versions_list_for_saving # First get the values from the draft attrs = draft_attributes # Now overwrite all values (self.class.versioned_columns - %w( version )).each do |col| attrs[col] = send(col) end attrs[:version_comment] = @version_comment || default_version_comment @version_comment = nil new_version = versions.build(attrs) new_version.version = new_record? ? 1 : (draft.version.to_i + 1) after_build_new_version(new_version) if respond_to?(:after_build_new_version) new_version end |
#create_or_update ⇒ Object
ActiveRecord 3.0.0 call chain ActiveRecord 3 now uses basic inheritence rather than alias_method_chain. The order in which ActiveRecord::Base includes methods (at the bottom of activerecord) repeatedly overrides save/save! with chains of ‘super’
Callstack order as observed
-
ActiveRecord::Base#save - The original method called by client
AR::Transactions#save
AR::Dirty#save
AR::Validations#save
ActiveRecord::Persistence#save
ActiveRecord::Persistence#create_or_update
AR::Callbacks#create_or_update (runs :save callbacks)
This aliases the original ActiveRecord::Base.save method, in order to change how calling save works. It should do the following things:
-
If the record is unchanged, no save is performed, but true is returned. (Skipping after_save callbacks)
-
If its an update, a new version is created and that is saved.
-
If new record, its version is set to 1, and its published if needed.
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/cms/behaviors/versioning.rb', line 170 def create_or_update logger.debug {"#{self.class}#create_or_update called. Published = #{!!publish_on_save}"} self.skip_callbacks = false unless different_from_last_draft? logger.debug {"No difference between this version and last. Skipping save"} self.skip_callbacks = true return true end logger.debug {"Saving #{self.class} #{self.attributes}"} if new_record? self.version = 1 # This should call ActiveRecord::Callbacks#create_or_update, which will correctly trigger the :save callback_chain saved_correctly = super changed_attributes.clear else logger.debug {"#{self.class}#update"} # Because we are 'skipping' the normal ActiveRecord update here, we must manually call the save callback chain. run_callbacks :save do saved_correctly = @new_version.save end end publish_if_needed return saved_correctly end |
#current_version ⇒ Object
298 299 300 |
# File 'lib/cms/behaviors/versioning.rb', line 298 def current_version find_version(self.version) end |
#default_version_comment ⇒ Object
129 130 131 132 133 134 135 |
# File 'lib/cms/behaviors/versioning.rb', line 129 def default_version_comment if new_record? "Created" else "Changed #{(changes.keys - %w[ version created_by_id updated_by_id ]).sort.join(', ')}" end end |
#different_from_last_draft? ⇒ Boolean
370 371 372 373 374 375 376 377 378 |
# File 'lib/cms/behaviors/versioning.rb', line 370 def different_from_last_draft? return true if self.changed? last_draft = self.draft return true unless last_draft (self.class.versioned_columns - %w( version )).each do |col| return true if self.send(col) != last_draft.send(col) end return false end |
#draft ⇒ Object
282 283 284 |
# File 'lib/cms/behaviors/versioning.rb', line 282 def draft versions.first(:order => "version desc") end |
#draft_attributes ⇒ Object
122 123 124 125 126 127 |
# File 'lib/cms/behaviors/versioning.rb', line 122 def draft_attributes # When there is no draft, we'll just copy the attributes from this object # Otherwise we need to use the draft d = new_record? ? self : draft self.class.versioned_columns.inject({}) { |attrs, col| attrs[col] = d.send(col); attrs } end |
#draft_version? ⇒ Boolean
286 287 288 |
# File 'lib/cms/behaviors/versioning.rb', line 286 def draft_version? version == draft.version end |
#find_version(number) ⇒ Object
302 303 304 |
# File 'lib/cms/behaviors/versioning.rb', line 302 def find_version(number) versions.first(:conditions => {:version => number}) end |
#initialize_version ⇒ Object
100 101 102 |
# File 'lib/cms/behaviors/versioning.rb', line 100 def initialize_version self.version = 1 if new_record? end |
#live_version ⇒ Object
290 291 292 |
# File 'lib/cms/behaviors/versioning.rb', line 290 def live_version find_version(self.class.find(id).version) end |
#live_version? ⇒ Boolean
294 295 296 |
# File 'lib/cms/behaviors/versioning.rb', line 294 def live_version? version == self.class.find(id).version end |
#publish_if_needed ⇒ Object
137 138 139 140 141 142 143 144 |
# File 'lib/cms/behaviors/versioning.rb', line 137 def publish_if_needed logger.debug { "#{self.class}#publish_if_needed. publish? = '#{!!@publish_on_save}'"} if @publish_on_save publish @publish_on_save = nil end end |
#revert ⇒ Object
340 341 342 343 |
# File 'lib/cms/behaviors/versioning.rb', line 340 def revert draft_version = draft.version revert_to(draft_version - 1) unless draft_version == 1 end |
#revert_to(version) ⇒ Object
356 357 358 359 |
# File 'lib/cms/behaviors/versioning.rb', line 356 def revert_to(version) revert_to_without_save(version) save end |
#revert_to_without_save(version) ⇒ Object
345 346 347 348 349 350 351 352 353 354 |
# File 'lib/cms/behaviors/versioning.rb', line 345 def revert_to_without_save(version) raise "Version parameter missing" if version.blank? self.revert_to_version = find_version(version) raise "Could not find version #{version}" unless revert_to_version (self.class.versioned_columns - ["version"]).each do |a| send("#{a}=", revert_to_version.send(a)) end self.version_comment = "Reverted to version #{version}" self end |
#save!(perform_validations = true) ⇒ Object
def save(perform_validations=true)
transaction do
#logger.info "..... Calling valid?"
return false unless !perform_validations || valid?
if different_from_last_draft?
#logger.info "..... Changes => #{changes.inspect}"
else
#logger.info "..... No Changes"
return true
end
#logger.info "..... Calling before_save"
return false if callback(:before_save) == false
if new_record?
#logger.info "..... Calling before_create"
return false if callback(:before_create) == false
else
#logger.info "..... Calling before_update"
return false if callback(:before_update) == false
end
#logger.info "..... Calling build_new_version"
new_version = build_new_version
#logger.info "..... Is new version valid? #{new_version.valid?}"
if new_record?
self.version = 1
#logger.info "..... Calling create_without_callbacks"
if result = create_without_callbacks
#logger.info "..... Calling after_create"
if callback(:after_create) != false
#logger.info "..... Calling after_save"
callback(:after_save)
end
if @publish_on_save
publish
@publish_on_save = nil
end
changed_attributes.clear
end
result
elsif new_version
#logger.info "..... Calling save"
if result = new_version.save
#logger.info "..... Calling after_save"
if callback(:after_update) != false
#logger.info "..... Calling after_update"
callback(:after_save)
end
if @publish_on_save
publish
@publish_on_save = nil
end
changed_attributes.clear
end
result
end
true
end
end
278 279 280 |
# File 'lib/cms/behaviors/versioning.rb', line 278 def save!(perform_validations=true) save(:validate=>perform_validations) || raise(ActiveRecord::RecordNotSaved.new(errors.)) end |
#version_comment ⇒ Object
361 362 363 |
# File 'lib/cms/behaviors/versioning.rb', line 361 def version_comment @version_comment end |
#version_comment=(version_comment) ⇒ Object
365 366 367 368 |
# File 'lib/cms/behaviors/versioning.rb', line 365 def version_comment=(version_comment) @version_comment = version_comment send(:changed_attributes)["version_comment"] = @version_comment end |