diff --git a/app/models/user.rb b/app/models/user.rb index 12554f6..36b9a4c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -23,7 +23,6 @@ require 'country_code_select/countries' require 'digest/md5' -require File.join(Rails.root, 'vendor', 'plugins', 'acts_as_versioned', 'lib', 'acts_as_versioned.rb') class User < ActiveRecord::Base include Extra diff --git a/config/initializers/legacy.rb b/config/initializers/legacy.rb new file mode 100644 index 0000000..f645ea7 --- /dev/null +++ b/config/initializers/legacy.rb @@ -0,0 +1,17 @@ +Dir.glob(File.join(Rails.root, "lib/plugins/*")).sort.each do |directory| + if File.directory?(directory) + lib = File.join(directory, "lib") + + if File.directory?(lib) + $:.unshift lib + ActiveSupport::Dependencies.autoload_paths += [lib] + end + + initializer = File.join(directory, "init.rb") + + if File.file?(initializer) + config = Ensl::Application.config + eval(File.read(initializer), binding, initializer) + end + end +end diff --git a/vendor/plugins/acts_as_versioned/CHANGELOG b/lib/plugins/acts_as_versioned/CHANGELOG similarity index 79% rename from vendor/plugins/acts_as_versioned/CHANGELOG rename to lib/plugins/acts_as_versioned/CHANGELOG index 1936211..a5d339c 100644 --- a/vendor/plugins/acts_as_versioned/CHANGELOG +++ b/lib/plugins/acts_as_versioned/CHANGELOG @@ -1,14 +1,4 @@ -*GIT* (version numbers are overrated) - -* 0.6 (19 Jul 2010) Rails 3 refactoring by gvarela! - -* (16 Jun 2008) Backwards Compatibility is overrated (big updates for rails 2.1) - - * Use ActiveRecord 2.1's dirty attribute checking instead [Asa Calow] - * Remove last traces of #non_versioned_fields - * Remove AR::Base.find_version and AR::Base.find_versions, rely on AR association proxies and named_scope - * Remove #versions_count, rely on AR association counter caching. - * Remove #versioned_attributes, basically the same as AR::Base.versioned_columns +*SVN* (version numbers are overrated) * (5 Oct 2006) Allow customization of #versions association options [Dan Peterson] diff --git a/vendor/plugins/acts_as_versioned/MIT-LICENSE b/lib/plugins/acts_as_versioned/MIT-LICENSE similarity index 100% rename from vendor/plugins/acts_as_versioned/MIT-LICENSE rename to lib/plugins/acts_as_versioned/MIT-LICENSE diff --git a/vendor/plugins/acts_as_versioned/README b/lib/plugins/acts_as_versioned/README similarity index 60% rename from vendor/plugins/acts_as_versioned/README rename to lib/plugins/acts_as_versioned/README index d2982c1..8961f05 100644 --- a/vendor/plugins/acts_as_versioned/README +++ b/lib/plugins/acts_as_versioned/README @@ -8,17 +8,21 @@ Install * gem install acts_as_versioned -<3 GitHub +Rubyforge project -* http://github.com/technoweenie/acts_as_versioned +* http://rubyforge.org/projects/ar-versioned -Gemcutter FTW +RDocs -* http://gemcutter.org/gems/acts_as_versioned +* http://ar-versioned.rubyforge.org Subversion -* http://svn.github.com/technoweenie/acts_as_versioned.git +* http://techno-weenie.net/svn/projects/acts_as_versioned + +Collaboa + +* http://collaboa.techno-weenie.net/repository/browse/acts_as_versioned Special thanks to Dreamer on ##rubyonrails for help in early testing. His ServerSideWiki (http://serversidewiki.com) was the first project to use acts_as_versioned in the wild. \ No newline at end of file diff --git a/vendor/plugins/acts_as_versioned/RUNNING_UNIT_TESTS b/lib/plugins/acts_as_versioned/RUNNING_UNIT_TESTS similarity index 100% rename from vendor/plugins/acts_as_versioned/RUNNING_UNIT_TESTS rename to lib/plugins/acts_as_versioned/RUNNING_UNIT_TESTS diff --git a/lib/plugins/acts_as_versioned/Rakefile b/lib/plugins/acts_as_versioned/Rakefile new file mode 100644 index 0000000..5bccb5d --- /dev/null +++ b/lib/plugins/acts_as_versioned/Rakefile @@ -0,0 +1,182 @@ +require 'rubygems' + +Gem::manage_gems + +require 'rake/rdoctask' +require 'rake/packagetask' +require 'rake/gempackagetask' +require 'rake/testtask' +require 'rake/contrib/rubyforgepublisher' + +PKG_NAME = 'acts_as_versioned' +PKG_VERSION = '0.3.1' +PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}" +PROD_HOST = "technoweenie@bidwell.textdrive.com" +RUBY_FORGE_PROJECT = 'ar-versioned' +RUBY_FORGE_USER = 'technoweenie' + +desc 'Default: run unit tests.' +task :default => :test + +desc 'Test the calculations plugin.' +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for the calculations plugin.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = "#{PKG_NAME} -- Simple versioning with active record models" + rdoc.options << '--line-numbers --inline-source' + rdoc.rdoc_files.include('README', 'CHANGELOG', 'RUNNING_UNIT_TESTS') + rdoc.rdoc_files.include('lib/**/*.rb') +end + +spec = Gem::Specification.new do |s| + s.name = PKG_NAME + s.version = PKG_VERSION + s.platform = Gem::Platform::RUBY + s.summary = "Simple versioning with active record models" + s.files = FileList["{lib,test}/**/*"].to_a + %w(README MIT-LICENSE CHANGELOG RUNNING_UNIT_TESTS) + s.files.delete "acts_as_versioned_plugin.sqlite.db" + s.files.delete "acts_as_versioned_plugin.sqlite3.db" + s.files.delete "test/debug.log" + s.require_path = 'lib' + s.autorequire = 'acts_as_versioned' + s.has_rdoc = true + s.test_files = Dir['test/**/*_test.rb'] + s.add_dependency 'activerecord', '>= 1.10.1' + s.add_dependency 'activesupport', '>= 1.1.1' + s.author = "Rick Olson" + s.email = "technoweenie@gmail.com" + s.homepage = "http://techno-weenie.net" +end + +Rake::GemPackageTask.new(spec) do |pkg| + pkg.need_tar = true +end + +desc "Publish the API documentation" +task :pdoc => [:rdoc] do + Rake::RubyForgePublisher.new(RUBY_FORGE_PROJECT, RUBY_FORGE_USER).upload +end + +desc 'Publish the gem and API docs' +task :publish => [:pdoc, :rubyforge_upload] + +desc "Publish the release files to RubyForge." +task :rubyforge_upload => :package do + files = %w(gem tgz).map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" } + + if RUBY_FORGE_PROJECT then + require 'net/http' + require 'open-uri' + + project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/" + project_data = open(project_uri) { |data| data.read } + group_id = project_data[/[?&]group_id=(\d+)/, 1] + raise "Couldn't get group id" unless group_id + + # This echos password to shell which is a bit sucky + if ENV["RUBY_FORGE_PASSWORD"] + password = ENV["RUBY_FORGE_PASSWORD"] + else + print "#{RUBY_FORGE_USER}@rubyforge.org's password: " + password = STDIN.gets.chomp + end + + login_response = Net::HTTP.start("rubyforge.org", 80) do |http| + data = [ + "login=1", + "form_loginname=#{RUBY_FORGE_USER}", + "form_pw=#{password}" + ].join("&") + http.post("/account/login.php", data) + end + + cookie = login_response["set-cookie"] + raise "Login failed" unless cookie + headers = { "Cookie" => cookie } + + release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}" + release_data = open(release_uri, headers) { |data| data.read } + package_id = release_data[/[?&]package_id=(\d+)/, 1] + raise "Couldn't get package id" unless package_id + + first_file = true + release_id = "" + + files.each do |filename| + basename = File.basename(filename) + file_ext = File.extname(filename) + file_data = File.open(filename, "rb") { |file| file.read } + + puts "Releasing #{basename}..." + + release_response = Net::HTTP.start("rubyforge.org", 80) do |http| + release_date = Time.now.strftime("%Y-%m-%d %H:%M") + type_map = { + ".zip" => "3000", + ".tgz" => "3110", + ".gz" => "3110", + ".gem" => "1400" + }; type_map.default = "9999" + type = type_map[file_ext] + boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor" + + query_hash = if first_file then + { + "group_id" => group_id, + "package_id" => package_id, + "release_name" => PKG_FILE_NAME, + "release_date" => release_date, + "type_id" => type, + "processor_id" => "8000", # Any + "release_notes" => "", + "release_changes" => "", + "preformatted" => "1", + "submit" => "1" + } + else + { + "group_id" => group_id, + "release_id" => release_id, + "package_id" => package_id, + "step2" => "1", + "type_id" => type, + "processor_id" => "8000", # Any + "submit" => "Add This File" + } + end + + query = "?" + query_hash.map do |(name, value)| + [name, URI.encode(value)].join("=") + end.join("&") + + data = [ + "--" + boundary, + "Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"", + "Content-Type: application/octet-stream", + "Content-Transfer-Encoding: binary", + "", file_data, "" + ].join("\x0D\x0A") + + release_headers = headers.merge( + "Content-Type" => "multipart/form-data; boundary=#{boundary}" + ) + + target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php" + http.post(target + query, data, release_headers) + end + + if first_file then + release_id = release_response.body[/release_id=(\d+)/, 1] + raise("Couldn't get release id") unless release_id + end + + first_file = false + end + end +end \ No newline at end of file diff --git a/lib/plugins/acts_as_versioned/init.rb b/lib/plugins/acts_as_versioned/init.rb new file mode 100644 index 0000000..5937bbc --- /dev/null +++ b/lib/plugins/acts_as_versioned/init.rb @@ -0,0 +1 @@ +require 'acts_as_versioned' \ No newline at end of file diff --git a/lib/plugins/acts_as_versioned/lib/acts_as_versioned.rb b/lib/plugins/acts_as_versioned/lib/acts_as_versioned.rb new file mode 100644 index 0000000..ffd3442 --- /dev/null +++ b/lib/plugins/acts_as_versioned/lib/acts_as_versioned.rb @@ -0,0 +1,568 @@ +# Copyright (c) 2005 Rick Olson +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +module ActiveRecord #:nodoc: + module Acts #:nodoc: + # Specify this act if you want to save a copy of the row in a versioned table. This assumes there is a + # versioned table ready and that your model has a version field. This works with optimistic locking if the lock_version + # column is present as well. + # + # The class for the versioned model is derived the first time it is seen. Therefore, if you change your database schema you have to restart + # your container for the changes to be reflected. In development mode this usually means restarting WEBrick. + # + # class Page < ActiveRecord::Base + # # assumes pages_versions table + # acts_as_versioned + # end + # + # Example: + # + # page = Page.create(:title => 'hello world!') + # page.version # => 1 + # + # page.title = 'hello world' + # page.save + # page.version # => 2 + # page.versions.size # => 2 + # + # page.revert_to(1) # using version number + # page.title # => 'hello world!' + # + # page.revert_to(page.versions.last) # using versioned instance + # page.title # => 'hello world' + # + # page.versions.earliest # efficient query to find the first version + # page.versions.latest # efficient query to find the most recently created version + # + # + # Simple Queries to page between versions + # + # page.versions.before(version) + # page.versions.after(version) + # + # Access the previous/next versions from the versioned model itself + # + # version = page.versions.latest + # version.previous # go back one version + # version.next # go forward one version + # + # See ActiveRecord::Acts::Versioned::ClassMethods#acts_as_versioned for configuration options + module Versioned + CALLBACKS = [:set_new_version, :save_version_on_create, :save_version?, :clear_altered_attributes] + def self.included(base) # :nodoc: + base.extend ClassMethods + end + + module ClassMethods + # == Configuration options + # + # * class_name - versioned model class name (default: PageVersion in the above example) + # * table_name - versioned model table name (default: page_versions in the above example) + # * foreign_key - foreign key used to relate the versioned model to the original model (default: page_id in the above example) + # * inheritance_column - name of the column to save the model's inheritance_column value for STI. (default: versioned_type) + # * version_column - name of the column in the model that keeps the version number (default: version) + # * sequence_name - name of the custom sequence to be used by the versioned model. + # * limit - number of revisions to keep, defaults to unlimited + # * if - symbol of method to check before saving a new version. If this method returns false, a new version is not saved. + # For finer control, pass either a Proc or modify Model#version_condition_met? + # + # acts_as_versioned :if => Proc.new { |auction| !auction.expired? } + # + # or... + # + # class Auction + # def version_condition_met? # totally bypasses the :if option + # !expired? + # end + # end + # + # * if_changed - Simple way of specifying attributes that are required to be changed before saving a model. This takes + # either a symbol or array of symbols. WARNING - This will attempt to overwrite any attribute setters you may have. + # Use this instead if you want to write your own attribute setters (and ignore if_changed): + # + # def name=(new_name) + # write_changed_attribute :name, new_name + # end + # + # * extend - Lets you specify a module to be mixed in both the original and versioned models. You can also just pass a block + # to create an anonymous mixin: + # + # class Auction + # acts_as_versioned do + # def started? + # !started_at.nil? + # end + # end + # end + # + # or... + # + # module AuctionExtension + # def started? + # !started_at.nil? + # end + # end + # class Auction + # acts_as_versioned :extend => AuctionExtension + # end + # + # Example code: + # + # @auction = Auction.find(1) + # @auction.started? + # @auction.versions.first.started? + # + # == Database Schema + # + # The model that you're versioning needs to have a 'version' attribute. The model is versioned + # into a table called #{model}_versions where the model name is singlular. The _versions table should + # contain all the fields you want versioned, the same version column, and a #{model}_id foreign key field. + # + # A lock_version field is also accepted if your model uses Optimistic Locking. If your table uses Single Table inheritance, + # then that field is reflected in the versioned model as 'versioned_type' by default. + # + # Acts_as_versioned comes prepared with the ActiveRecord::Acts::Versioned::ActMethods::ClassMethods#create_versioned_table + # method, perfect for a migration. It will also create the version column if the main model does not already have it. + # + # class AddVersions < ActiveRecord::Migration + # def self.up + # # create_versioned_table takes the same options hash + # # that create_table does + # Post.create_versioned_table + # end + # + # def self.down + # Post.drop_versioned_table + # end + # end + # + # == Changing What Fields Are Versioned + # + # By default, acts_as_versioned will version all but these fields: + # + # [self.primary_key, inheritance_column, 'version', 'lock_version', versioned_inheritance_column] + # + # You can add or change those by modifying #non_versioned_columns. Note that this takes strings and not symbols. + # + # class Post < ActiveRecord::Base + # acts_as_versioned + # self.non_versioned_columns << 'comments_count' + # end + # + def acts_as_versioned(options = {}, &extension) + # don't allow multiple calls + return if self.included_modules.include?(ActiveRecord::Acts::Versioned::ActMethods) + + send :include, ActiveRecord::Acts::Versioned::ActMethods + + cattr_accessor :versioned_class_name, :versioned_foreign_key, :versioned_table_name, :versioned_inheritance_column, + :version_column, :max_version_limit, :track_altered_attributes, :version_condition, :version_sequence_name, :non_versioned_columns, + :version_association_options + + # legacy + alias_method :non_versioned_fields, :non_versioned_columns + alias_method :non_versioned_fields=, :non_versioned_columns= + + class << self + alias_method :non_versioned_fields, :non_versioned_columns + alias_method :non_versioned_fields=, :non_versioned_columns= + end + + send :attr_accessor, :altered_attributes + + self.versioned_class_name = options[:class_name] || "Version" + self.versioned_foreign_key = options[:foreign_key] || self.to_s.foreign_key + self.versioned_table_name = options[:table_name] || "#{table_name_prefix}#{base_class.name.demodulize.underscore}_versions#{table_name_suffix}" + self.versioned_inheritance_column = options[:inheritance_column] || "versioned_#{inheritance_column}" + self.version_column = options[:version_column] || 'version' + self.version_sequence_name = options[:sequence_name] + self.max_version_limit = options[:limit].to_i + self.version_condition = options[:if] || true + self.non_versioned_columns = [self.primary_key, inheritance_column, 'version', 'lock_version', versioned_inheritance_column] + self.version_association_options = { + :class_name => "#{self.to_s}::#{versioned_class_name}", + :foreign_key => versioned_foreign_key, + :dependent => :delete_all + }.merge(options[:association_options] || {}) + + if block_given? + extension_module_name = "#{versioned_class_name}Extension" + silence_warnings do + self.const_set(extension_module_name, Module.new(&extension)) + end + + options[:extend] = self.const_get(extension_module_name) + end + + class_eval do + has_many :versions, version_association_options do + # finds earliest version of this record + def earliest + @earliest ||= order('version').first + end + + # find latest version of this record + def latest + @latest ||= order('version desc').first + end + end + before_save :set_new_version + after_create :save_version_on_create + after_update :save_version + after_save :clear_old_versions + after_save :clear_altered_attributes + + unless options[:if_changed].nil? + self.track_altered_attributes = true + options[:if_changed] = [options[:if_changed]] unless options[:if_changed].is_a?(Array) + options[:if_changed].each do |attr_name| + define_method("#{attr_name}=") do |value| + write_changed_attribute attr_name, value + end + end + end + + include options[:extend] if options[:extend].is_a?(Module) + end + + # create the dynamic versioned model + const_set(versioned_class_name, Class.new(ActiveRecord::Base)).class_eval do + def self.reloadable? ; false ; end + # find first version before the given version + def self.before(version) + order('version desc'). + where("#{original_class.versioned_foreign_key} = ? and version < ?", version.send(original_class.versioned_foreign_key), version.version). + first + end + + # find first version after the given version. + def self.after(version) + order('version'). + where("#{original_class.versioned_foreign_key} = ? and version > ?", version.send(original_class.versioned_foreign_key), version.version). + first + end + + def previous + self.class.before(self) + end + + def next + self.class.after(self) + end + + def versions_count + page.version + end + end + + versioned_class.cattr_accessor :original_class + versioned_class.original_class = self + versioned_class.table_name = versioned_table_name + versioned_class.belongs_to self.to_s.demodulize.underscore.to_sym, + :class_name => "::#{self.to_s}", + :foreign_key => versioned_foreign_key + versioned_class.send :include, options[:extend] if options[:extend].is_a?(Module) + versioned_class.set_sequence_name version_sequence_name if version_sequence_name + end + end + + module ActMethods + def self.included(base) # :nodoc: + base.extend ClassMethods + end + + # Finds a specific version of this record + def find_version(version = nil) + self.class.find_version(id, version) + end + + # Saves a version of the model if applicable + def save_version + save_version_on_create if save_version? + end + + # Saves a version of the model in the versioned table. This is called in the after_save callback by default + def save_version_on_create + rev = self.class.versioned_class.new + self.clone_versioned_model(self, rev) + rev.version = send(self.class.version_column) + rev.send("#{self.class.versioned_foreign_key}=", self.id) + rev.save + end + + # Clears old revisions if a limit is set with the :limit option in acts_as_versioned. + # Override this method to set your own criteria for clearing old versions. + def clear_old_versions + return if self.class.max_version_limit == 0 + excess_baggage = send(self.class.version_column).to_i - self.class.max_version_limit + if excess_baggage > 0 + sql = "DELETE FROM #{self.class.versioned_table_name} WHERE version <= #{excess_baggage} AND #{self.class.versioned_foreign_key} = #{self.id}" + self.class.versioned_class.connection.execute sql + end + end + + def versions_count + version + end + + # Reverts a model to a given version. Takes either a version number or an instance of the versioned model + def revert_to(version) + if version.is_a?(self.class.versioned_class) + return false unless version.send(self.class.versioned_foreign_key) == self.id and !version.new_record? + else + return false unless version = versions.find_by_version(version) + end + self.clone_versioned_model(version, self) + self.send("#{self.class.version_column}=", version.version) + true + end + + # Reverts a model to a given version and saves the model. + # Takes either a version number or an instance of the versioned model + def revert_to!(version) + revert_to(version) ? save_without_revision : false + end + + # Temporarily turns off Optimistic Locking while saving. Used when reverting so that a new version is not created. + def save_without_revision + save_without_revision! + true + rescue + false + end + + def save_without_revision! + without_locking do + without_revision do + save! + end + end + end + + # Returns an array of attribute keys that are versioned. See non_versioned_columns + def versioned_attributes + self.attributes.keys.select { |k| !self.class.non_versioned_columns.include?(k) } + end + + # If called with no parameters, gets whether the current model has changed and needs to be versioned. + # If called with a single parameter, gets whether the parameter has changed. + def changed?(attr_name = nil) + attr_name.nil? ? + (!self.class.track_altered_attributes || (altered_attributes && altered_attributes.length > 0)) : + (altered_attributes && altered_attributes.include?(attr_name.to_s)) + end + + # keep old dirty? method + alias_method :dirty?, :changed? + + # Clones a model. Used when saving a new version or reverting a model's version. + def clone_versioned_model(orig_model, new_model) + self.versioned_attributes.each do |key| + new_model.send("#{key}=", orig_model.send(key)) if orig_model.respond_to?(key) + end + + if self.class.columns_hash.include?(self.class.inheritance_column) + if orig_model.is_a?(self.class.versioned_class) + new_model[new_model.class.inheritance_column] = orig_model[self.class.versioned_inheritance_column] + elsif new_model.is_a?(self.class.versioned_class) + new_model[self.class.versioned_inheritance_column] = orig_model[orig_model.class.inheritance_column] + end + end + end + + # Checks whether a new version shall be saved or not. Calls version_condition_met? and changed?. + def save_version? + version_condition_met? && changed? + end + + # Checks condition set in the :if option to check whether a revision should be created or not. Override this for + # custom version condition checking. + def version_condition_met? + case + when version_condition.is_a?(Symbol) + send(version_condition) + when version_condition.respond_to?(:call) && (version_condition.arity == 1 || version_condition.arity == -1) + version_condition.call(self) + else + version_condition + end + end + + # Executes the block with the versioning callbacks disabled. + # + # @foo.without_revision do + # @foo.save + # end + # + def without_revision(&block) + self.class.without_revision(&block) + end + + # Turns off optimistic locking for the duration of the block + # + # @foo.without_locking do + # @foo.save + # end + # + def without_locking(&block) + self.class.without_locking(&block) + end + + def empty_callback() end #:nodoc: + + protected + # sets the new version before saving, unless you're using optimistic locking. In that case, let it take care of the version. + def set_new_version + self.send("#{self.class.version_column}=", self.next_version) if new_record? || (!locking_enabled? && save_version?) + end + + # Gets the next available version for the current record, or 1 for a new record + def next_version + return 1 if new_record? + (versions.maximum('version') || 0) + 1 + end + + # clears current changed attributes. Called after save. + def clear_altered_attributes + self.altered_attributes = [] + end + + def write_changed_attribute(attr_name, attr_value) + # Convert to db type for comparison. Avoids failing Float<=>String comparisons. + attr_value_for_db = self.class.columns_hash[attr_name.to_s].type_cast_from_database(attr_value) + (self.altered_attributes ||= []) << attr_name.to_s unless self.changed?(attr_name) || self.send(attr_name) == attr_value_for_db + write_attribute(attr_name, attr_value_for_db) + end + + module ClassMethods + # Finds a specific version of a specific row of this model + def find_version(id, version = nil) + return find(id) unless version + + conditions = ["#{versioned_foreign_key} = ? AND version = ?", id, version] + options = { :conditions => conditions, :limit => 1 } + + if result = find_versions(id, options).first + result + else + raise RecordNotFound, "Couldn't find #{name} with ID=#{id} and VERSION=#{version}" + end + end + + # Finds versions of a specific model. Takes an options hash like find + def find_versions(id, options = {}) + versioned_class.all({ + :conditions => ["#{versioned_foreign_key} = ?", id], + :order => 'version' }.merge(options)) + end + + # Returns an array of columns that are versioned. See non_versioned_columns + def versioned_columns + self.columns.select { |c| !non_versioned_columns.include?(c.name) } + end + + # Returns an instance of the dynamic versioned model + def versioned_class + const_get versioned_class_name + end + + # Rake migration task to create the versioned table using options passed to acts_as_versioned + def create_versioned_table(create_table_options = {}) + # create version column in main table if it does not exist + if !self.content_columns.find { |c| %w(version lock_version).include? c.name } + self.connection.add_column table_name, :version, :integer + end + + self.connection.create_table(versioned_table_name, create_table_options) do |t| + t.column versioned_foreign_key, :integer + t.column :version, :integer + end + + updated_col = nil + self.versioned_columns.each do |col| + updated_col = col if !updated_col && %(updated_at updated_on).include?(col.name) + self.connection.add_column versioned_table_name, col.name, col.type, + :limit => col.limit, + :default => col.default, + :scale => col.scale, + :precision => col.precision + end + + if type_col = self.columns_hash[inheritance_column] + self.connection.add_column versioned_table_name, versioned_inheritance_column, type_col.type, + :limit => type_col.limit, + :default => type_col.default, + :scale => type_col.scale, + :precision => type_col.precision + end + + if updated_col.nil? + self.connection.add_column versioned_table_name, :updated_at, :timestamp + end + end + + # Rake migration task to drop the versioned table + def drop_versioned_table + self.connection.drop_table versioned_table_name + end + + # Executes the block with the versioning callbacks disabled. + # + # Foo.without_revision do + # @foo.save + # end + # + def without_revision(&block) + class_eval do + CALLBACKS.each do |attr_name| + alias_method "orig_#{attr_name}".to_sym, attr_name + alias_method attr_name, :empty_callback + end + end + block.call + ensure + class_eval do + CALLBACKS.each do |attr_name| + alias_method attr_name, "orig_#{attr_name}".to_sym + end + end + end + + # Turns off optimistic locking for the duration of the block + # + # Foo.without_locking do + # @foo.save + # end + # + def without_locking(&block) + current = ActiveRecord::Base.lock_optimistically + ActiveRecord::Base.lock_optimistically = false if current + result = block.call + ActiveRecord::Base.lock_optimistically = true if current + result + end + end + end + end + end +end + +ActiveRecord::Base.send :include, ActiveRecord::Acts::Versioned \ No newline at end of file diff --git a/vendor/plugins/acts_as_versioned/test/abstract_unit.rb b/lib/plugins/acts_as_versioned/test/abstract_unit.rb similarity index 75% rename from vendor/plugins/acts_as_versioned/test/abstract_unit.rb rename to lib/plugins/acts_as_versioned/test/abstract_unit.rb index f8d2c27..86f5062 100644 --- a/vendor/plugins/acts_as_versioned/test/abstract_unit.rb +++ b/lib/plugins/acts_as_versioned/test/abstract_unit.rb @@ -1,20 +1,15 @@ -require "rubygems" -require "bundler" -Bundler.setup(:default, :development) - +$:.unshift(File.dirname(__FILE__) + '/../../../rails/activesupport/lib') +$:.unshift(File.dirname(__FILE__) + '/../../../rails/activerecord/lib') $:.unshift(File.dirname(__FILE__) + '/../lib') require 'test/unit' -require 'active_support' -require 'active_record' -require 'active_record/fixtures' -require 'active_record/test_case' - begin - require 'ruby-debug' - Debugger.start + require 'active_support' + require 'active_record' + require 'active_record/fixtures' rescue LoadError + require 'rubygems' + retry end - require 'acts_as_versioned' config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml')) @@ -32,18 +27,15 @@ if ENV['DB'] == 'postgresql' ActiveRecord::Base.connection.execute "ALTER TABLE widget_versions ADD COLUMN id INTEGER PRIMARY KEY DEFAULT nextval('widgets_seq');" end -class ActiveSupport::TestCase #:nodoc: - include ActiveRecord::TestFixtures +Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/" +$:.unshift(Test::Unit::TestCase.fixture_path) - self.fixture_path = File.dirname(__FILE__) + "/fixtures/" - +class Test::Unit::TestCase #:nodoc: # Turn off transactional fixtures if you're working with MyISAM tables in MySQL self.use_transactional_fixtures = true - + # Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david) self.use_instantiated_fixtures = false # Add more helper methods to be used by all tests here... -end - -$:.unshift(ActiveSupport::TestCase.fixture_path) \ No newline at end of file +end \ No newline at end of file diff --git a/lib/plugins/acts_as_versioned/test/database.yml b/lib/plugins/acts_as_versioned/test/database.yml new file mode 100644 index 0000000..506e6bd --- /dev/null +++ b/lib/plugins/acts_as_versioned/test/database.yml @@ -0,0 +1,18 @@ +sqlite: + :adapter: sqlite + :dbfile: acts_as_versioned_plugin.sqlite.db +sqlite3: + :adapter: sqlite3 + :dbfile: acts_as_versioned_plugin.sqlite3.db +postgresql: + :adapter: postgresql + :username: postgres + :password: postgres + :database: acts_as_versioned_plugin_test + :min_messages: ERROR +mysql: + :adapter: mysql + :host: localhost + :username: rails + :password: + :database: acts_as_versioned_plugin_test \ No newline at end of file diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/authors.yml b/lib/plugins/acts_as_versioned/test/fixtures/authors.yml similarity index 100% rename from vendor/plugins/acts_as_versioned/test/fixtures/authors.yml rename to lib/plugins/acts_as_versioned/test/fixtures/authors.yml diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/landmark.rb b/lib/plugins/acts_as_versioned/test/fixtures/landmark.rb similarity index 100% rename from vendor/plugins/acts_as_versioned/test/fixtures/landmark.rb rename to lib/plugins/acts_as_versioned/test/fixtures/landmark.rb diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/landmark_versions.yml b/lib/plugins/acts_as_versioned/test/fixtures/landmark_versions.yml similarity index 100% rename from vendor/plugins/acts_as_versioned/test/fixtures/landmark_versions.yml rename to lib/plugins/acts_as_versioned/test/fixtures/landmark_versions.yml diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/landmarks.yml b/lib/plugins/acts_as_versioned/test/fixtures/landmarks.yml similarity index 68% rename from vendor/plugins/acts_as_versioned/test/fixtures/landmarks.yml rename to lib/plugins/acts_as_versioned/test/fixtures/landmarks.yml index cf06390..46d9617 100644 --- a/vendor/plugins/acts_as_versioned/test/fixtures/landmarks.yml +++ b/lib/plugins/acts_as_versioned/test/fixtures/landmarks.yml @@ -3,5 +3,4 @@ washington: name: Washington, D.C. latitude: 38.895 longitude: -77.036667 - doesnt_trigger_version: This is not important version: 1 diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/locked_pages.yml b/lib/plugins/acts_as_versioned/test/fixtures/locked_pages.yml similarity index 100% rename from vendor/plugins/acts_as_versioned/test/fixtures/locked_pages.yml rename to lib/plugins/acts_as_versioned/test/fixtures/locked_pages.yml diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/locked_pages_revisions.yml b/lib/plugins/acts_as_versioned/test/fixtures/locked_pages_revisions.yml similarity index 83% rename from vendor/plugins/acts_as_versioned/test/fixtures/locked_pages_revisions.yml rename to lib/plugins/acts_as_versioned/test/fixtures/locked_pages_revisions.yml index 3a1be5a..5c978e6 100644 --- a/vendor/plugins/acts_as_versioned/test/fixtures/locked_pages_revisions.yml +++ b/lib/plugins/acts_as_versioned/test/fixtures/locked_pages_revisions.yml @@ -2,26 +2,26 @@ welcome_1: id: 1 page_id: 1 title: Welcome to the weblg - lock_version: 23 + version: 23 version_type: LockedPage welcome_2: id: 2 page_id: 1 title: Welcome to the weblog - lock_version: 24 + version: 24 version_type: LockedPage thinking_1: id: 3 page_id: 2 title: So I was thinking!!! - lock_version: 23 + version: 23 version_type: SpecialLockedPage thinking_2: id: 4 page_id: 2 title: So I was thinking - lock_version: 24 + version: 24 version_type: SpecialLockedPage diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb b/lib/plugins/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb similarity index 74% rename from vendor/plugins/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb rename to lib/plugins/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb index 5007b16..9512b5e 100644 --- a/vendor/plugins/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb +++ b/lib/plugins/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb @@ -2,8 +2,6 @@ class AddVersionedTables < ActiveRecord::Migration def self.up create_table("things") do |t| t.column :title, :text - t.column :price, :decimal, :precision => 7, :scale => 2 - t.column :type, :string end Thing.create_versioned_table end diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/page.rb b/lib/plugins/acts_as_versioned/test/fixtures/page.rb similarity index 100% rename from vendor/plugins/acts_as_versioned/test/fixtures/page.rb rename to lib/plugins/acts_as_versioned/test/fixtures/page.rb diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/page_versions.yml b/lib/plugins/acts_as_versioned/test/fixtures/page_versions.yml similarity index 100% rename from vendor/plugins/acts_as_versioned/test/fixtures/page_versions.yml rename to lib/plugins/acts_as_versioned/test/fixtures/page_versions.yml diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/pages.yml b/lib/plugins/acts_as_versioned/test/fixtures/pages.yml similarity index 66% rename from vendor/plugins/acts_as_versioned/test/fixtures/pages.yml rename to lib/plugins/acts_as_versioned/test/fixtures/pages.yml index 9f4ab54..07ac51f 100644 --- a/vendor/plugins/acts_as_versioned/test/fixtures/pages.yml +++ b/lib/plugins/acts_as_versioned/test/fixtures/pages.yml @@ -4,5 +4,4 @@ welcome: body: Such a lovely day version: 24 author_id: 1 - revisor_id: 1 - created_on: "2008-01-01 00:00:00" \ No newline at end of file + revisor_id: 1 \ No newline at end of file diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/widget.rb b/lib/plugins/acts_as_versioned/test/fixtures/widget.rb similarity index 100% rename from vendor/plugins/acts_as_versioned/test/fixtures/widget.rb rename to lib/plugins/acts_as_versioned/test/fixtures/widget.rb diff --git a/vendor/plugins/acts_as_versioned/test/migration_test.rb b/lib/plugins/acts_as_versioned/test/migration_test.rb similarity index 97% rename from vendor/plugins/acts_as_versioned/test/migration_test.rb rename to lib/plugins/acts_as_versioned/test/migration_test.rb index a908506..4ead4a8 100644 --- a/vendor/plugins/acts_as_versioned/test/migration_test.rb +++ b/lib/plugins/acts_as_versioned/test/migration_test.rb @@ -6,7 +6,7 @@ if ActiveRecord::Base.connection.supports_migrations? acts_as_versioned end - class MigrationTest < ActiveSupport::TestCase + class MigrationTest < Test::Unit::TestCase self.use_transactional_fixtures = false def teardown if ActiveRecord::Base.connection.respond_to?(:initialize_schema_information) diff --git a/vendor/plugins/acts_as_versioned/test/schema.rb b/lib/plugins/acts_as_versioned/test/schema.rb similarity index 77% rename from vendor/plugins/acts_as_versioned/test/schema.rb rename to lib/plugins/acts_as_versioned/test/schema.rb index 49e6c0f..7d5153d 100644 --- a/vendor/plugins/acts_as_versioned/test/schema.rb +++ b/lib/plugins/acts_as_versioned/test/schema.rb @@ -3,7 +3,6 @@ ActiveRecord::Schema.define(:version => 0) do t.column :version, :integer t.column :title, :string, :limit => 255 t.column :body, :text - t.column :created_on, :datetime t.column :updated_on, :datetime t.column :author_id, :integer t.column :revisor_id, :integer @@ -14,14 +13,11 @@ ActiveRecord::Schema.define(:version => 0) do t.column :version, :integer t.column :title, :string, :limit => 255 t.column :body, :text - t.column :created_on, :datetime t.column :updated_on, :datetime t.column :author_id, :integer t.column :revisor_id, :integer end - add_index :page_versions, [:page_id, :version], :unique => true - create_table :authors, :force => true do |t| t.column :page_id, :integer t.column :name, :string @@ -30,20 +26,16 @@ ActiveRecord::Schema.define(:version => 0) do create_table :locked_pages, :force => true do |t| t.column :lock_version, :integer t.column :title, :string, :limit => 255 - t.column :body, :text t.column :type, :string, :limit => 255 end create_table :locked_pages_revisions, :force => true do |t| t.column :page_id, :integer - t.column :lock_version, :integer + t.column :version, :integer t.column :title, :string, :limit => 255 - t.column :body, :text t.column :version_type, :string, :limit => 255 t.column :updated_at, :datetime end - - add_index :locked_pages_revisions, [:page_id, :lock_version], :unique => true create_table :widgets, :force => true do |t| t.column :name, :string, :limit => 50 @@ -59,13 +51,10 @@ ActiveRecord::Schema.define(:version => 0) do t.column :updated_at, :datetime end - add_index :widget_versions, [:widget_id, :version], :unique => true - create_table :landmarks, :force => true do |t| t.column :name, :string t.column :latitude, :float t.column :longitude, :float - t.column :doesnt_trigger_version,:string t.column :version, :integer end @@ -74,9 +63,6 @@ ActiveRecord::Schema.define(:version => 0) do t.column :name, :string t.column :latitude, :float t.column :longitude, :float - t.column :doesnt_trigger_version,:string t.column :version, :integer end - - add_index :landmark_versions, [:landmark_id, :version], :unique => true end diff --git a/vendor/plugins/acts_as_versioned/test/versioned_test.rb b/lib/plugins/acts_as_versioned/test/versioned_test.rb similarity index 79% rename from vendor/plugins/acts_as_versioned/test/versioned_test.rb rename to lib/plugins/acts_as_versioned/test/versioned_test.rb index b8fe8dd..a7bc208 100644 --- a/vendor/plugins/acts_as_versioned/test/versioned_test.rb +++ b/lib/plugins/acts_as_versioned/test/versioned_test.rb @@ -2,7 +2,7 @@ require File.join(File.dirname(__FILE__), 'abstract_unit') require File.join(File.dirname(__FILE__), 'fixtures/page') require File.join(File.dirname(__FILE__), 'fixtures/widget') -class VersionedTest < ActiveSupport::TestCase +class VersionedTest < Test::Unit::TestCase fixtures :pages, :page_versions, :locked_pages, :locked_pages_revisions, :authors, :landmarks, :landmark_versions set_fixture_class :page_versions => Page::Version @@ -32,7 +32,7 @@ class VersionedTest < ActiveSupport::TestCase assert_equal 24, p.version assert_equal 'Welcome to the weblog', p.title - assert p.revert_to!(23), "Couldn't revert to 23" + assert p.revert_to!(p.versions.first.version), "Couldn't revert to 23" assert_equal 23, p.version assert_equal 'Welcome to the weblg', p.title end @@ -59,7 +59,7 @@ class VersionedTest < ActiveSupport::TestCase assert_equal 24, p.version assert_equal 'Welcome to the weblog', p.title - assert p.revert_to!(p.versions.find_by_version(23)), "Couldn't revert to 23" + assert p.revert_to!(p.versions.first), "Couldn't revert to 23" assert_equal 23, p.version assert_equal 'Welcome to the weblg', p.title end @@ -81,7 +81,7 @@ class VersionedTest < ActiveSupport::TestCase assert_equal 'Welcome to the weblog', p.title assert_equal 'LockedPage', p.versions.first.version_type - assert p.revert_to!(p.versions.first.lock_version), "Couldn't revert to 23" + assert p.revert_to!(p.versions.first.version), "Couldn't revert to 23" assert_equal 'Welcome to the weblg', p.title assert_equal 'LockedPage', p.versions.first.version_type end @@ -108,7 +108,7 @@ class VersionedTest < ActiveSupport::TestCase p = locked_pages(:thinking) assert_equal 'So I was thinking', p.title - assert p.revert_to!(p.versions.first.lock_version), "Couldn't revert to 1" + assert p.revert_to!(p.versions.first.version), "Couldn't revert to 1" assert_equal 'So I was thinking!!!', p.title assert_equal 'SpecialLockedPage', p.versions.first.version_type end @@ -147,15 +147,15 @@ class VersionedTest < ActiveSupport::TestCase p = Page.create! :title => "title" assert_equal 1, p.version # version does not increment - assert_equal 1, p.versions.count + assert_equal 1, p.versions(true).size p.update_attributes(:title => 'new title') assert_equal 1, p.version # version does not increment - assert_equal 1, p.versions.count + assert_equal 1, p.versions(true).size p.update_attributes(:title => 'a title') assert_equal 2, p.version - assert_equal 2, p.versions.count + assert_equal 2, p.versions(true).size # reset original if condition Page.class_eval { alias_method :feeling_good?, :old_feeling_good } @@ -168,15 +168,15 @@ class VersionedTest < ActiveSupport::TestCase p = Page.create! :title => "title" assert_equal 1, p.version # version does not increment - assert_equal 1, p.versions.count + assert_equal 1, p.versions(true).size p.update_attributes(:title => 'a title') assert_equal 1, p.version # version does not increment - assert_equal 1, p.versions.count + assert_equal 1, p.versions(true).size p.update_attributes(:title => 'b title') assert_equal 2, p.version - assert_equal 2, p.versions.count + assert_equal 2, p.versions(true).size # reset original if condition Page.version_condition = old_condition @@ -187,10 +187,7 @@ class VersionedTest < ActiveSupport::TestCase p.save p.save 5.times do |i| - p.title = "title#{i}" - p.save - assert_equal "title#{i}", p.title - assert_equal (i+2), p.version + assert_page_title p, i end end @@ -199,10 +196,7 @@ class VersionedTest < ActiveSupport::TestCase p.update_attributes(:title => "title1") p.update_attributes(:title => "title2") 5.times do |i| - p.title = "title#{i}" - p.save - assert_equal "title#{i}", p.title - assert_equal (i+4), p.lock_version + assert_page_title p, i, :lock_version assert p.versions(true).size <= 2, "locked version can only store 2 versions" end end @@ -213,12 +207,17 @@ class VersionedTest < ActiveSupport::TestCase assert SpecialLockedPage.track_altered_attributes end + def test_version_order + assert_equal 23, pages(:welcome).versions.first.version + assert_equal 24, pages(:welcome).versions.last.version + end + def test_track_altered_attributes p = LockedPage.create! :title => "title" assert_equal 1, p.lock_version assert_equal 1, p.versions(true).size - p.body = 'whoa' + p.title = 'title' assert !p.save_version? p.save assert_equal 2, p.lock_version # still increments version because of optimistic locking @@ -237,12 +236,32 @@ class VersionedTest < ActiveSupport::TestCase assert_equal 2, p.versions(true).size # version 1 deleted end + def assert_page_title(p, i, version_field = :version) + p.title = "title#{i}" + p.save + assert_equal "title#{i}", p.title + assert_equal (i+4), p.send(version_field) + end + def test_find_versions - assert_equal 1, locked_pages(:welcome).versions.find(:all, :conditions => ['title LIKE ?', '%weblog%']).size + assert_equal 2, locked_pages(:welcome).versions.size + assert_equal 1, locked_pages(:welcome).versions.find(:all, :conditions => ['title LIKE ?', '%weblog%']).length + assert_equal 2, locked_pages(:welcome).versions.find(:all, :conditions => ['title LIKE ?', '%web%']).length + assert_equal 0, locked_pages(:thinking).versions.find(:all, :conditions => ['title LIKE ?', '%web%']).length + assert_equal 2, locked_pages(:welcome).versions.length end def test_find_version - assert_equal page_versions(:welcome_1), pages(:welcome).versions.find_by_version(23) + assert_equal page_versions(:welcome_1), Page.find_version(pages(:welcome).id, 23) + assert_equal page_versions(:welcome_2), Page.find_version(pages(:welcome).id, 24) + assert_equal pages(:welcome), Page.find_version(pages(:welcome).id) + + assert_equal page_versions(:welcome_1), pages(:welcome).find_version(23) + assert_equal page_versions(:welcome_2), pages(:welcome).find_version(24) + assert_equal pages(:welcome), pages(:welcome).find_version + + assert_raise(ActiveRecord::RecordNotFound) { Page.find_version(pages(:welcome).id, 1) } + assert_raise(ActiveRecord::RecordNotFound) { Page.find_version(0, 23) } end def test_with_sequence @@ -270,6 +289,7 @@ class VersionedTest < ActiveSupport::TestCase association = Page.reflect_on_association(:versions) options = association.options assert_equal :delete_all, options[:dependent] + assert_equal 'version', options[:order] association = Widget.reflect_on_association(:versions) options = association.options @@ -320,51 +340,8 @@ class VersionedTest < ActiveSupport::TestCase end def test_should_find_version_count - assert_equal 2, pages(:welcome).versions.size - end - - def test_if_changed_creates_version_if_a_listed_column_is_changed - landmarks(:washington).name = "Washington" - assert landmarks(:washington).changed? - assert landmarks(:washington).altered? - end - - def test_if_changed_creates_version_if_all_listed_columns_are_changed - landmarks(:washington).name = "Washington" - landmarks(:washington).latitude = 1.0 - landmarks(:washington).longitude = 1.0 - assert landmarks(:washington).changed? - assert landmarks(:washington).altered? - end - - def test_if_changed_does_not_create_new_version_if_unlisted_column_is_changed - landmarks(:washington).doesnt_trigger_version = "This should not trigger version" - assert landmarks(:washington).changed? - assert !landmarks(:washington).altered? - end - - def test_without_locking_temporarily_disables_optimistic_locking - enabled1 = false - block_called = false - - ActiveRecord::Base.lock_optimistically = true - LockedPage.without_locking do - enabled1 = ActiveRecord::Base.lock_optimistically - block_called = true - end - enabled2 = ActiveRecord::Base.lock_optimistically - - assert block_called - assert !enabled1 - assert enabled2 - end - - def test_without_locking_reverts_optimistic_locking_settings_if_block_raises_exception - assert_raises(RuntimeError) do - LockedPage.without_locking do - raise RuntimeError, "oh noes" - end - end - assert ActiveRecord::Base.lock_optimistically + assert_equal 24, pages(:welcome).versions_count + assert_equal 24, page_versions(:welcome_1).versions_count + assert_equal 24, page_versions(:welcome_2).versions_count end end \ No newline at end of file diff --git a/vendor/plugins/acts_as_versioned/.document b/vendor/plugins/acts_as_versioned/.document deleted file mode 100644 index ecf3673..0000000 --- a/vendor/plugins/acts_as_versioned/.document +++ /dev/null @@ -1,5 +0,0 @@ -README.rdoc -lib/**/*.rb -bin/* -features/**/*.feature -LICENSE diff --git a/vendor/plugins/acts_as_versioned/Gemfile b/vendor/plugins/acts_as_versioned/Gemfile deleted file mode 100644 index a1be110..0000000 --- a/vendor/plugins/acts_as_versioned/Gemfile +++ /dev/null @@ -1,7 +0,0 @@ -source 'http://rubygems.org' - -group :development do - gem 'rails', '3.1.0' - gem 'sqlite3-ruby', '1.3.1' - gem 'mysql', '2.8.1' -end \ No newline at end of file diff --git a/vendor/plugins/acts_as_versioned/Rakefile b/vendor/plugins/acts_as_versioned/Rakefile deleted file mode 100644 index 9dc513d..0000000 --- a/vendor/plugins/acts_as_versioned/Rakefile +++ /dev/null @@ -1,146 +0,0 @@ -require 'rubygems' -require 'rake' -require 'date' - -############################################################################# -# -# Helper functions -# -############################################################################# - -def name - @name ||= Dir['*.gemspec'].first.split('.').first -end - -def version - line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/] - line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1] -end - -def date - Date.today.to_s -end - -def rubyforge_project - name -end - -def gemspec_file - "#{name}.gemspec" -end - -def gem_file - "#{name}-#{version}.gem" -end - -def replace_header(head, header_name) - head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"} -end - -############################################################################# -# -# Standard tasks -# -############################################################################# - -task :default => :test - -require 'rake/testtask' -Rake::TestTask.new(:test) do |test| - test.libs << 'lib' << 'test' - test.pattern = 'test/**/*_test.rb' - test.verbose = true -end - -desc "Generate RCov test coverage and open in your browser" -task :coverage do - require 'rcov' - sh "rm -fr coverage" - sh "rcov test/test_*.rb" - sh "open coverage/index.html" -end - -require 'rake/rdoctask' -Rake::RDocTask.new do |rdoc| - rdoc.rdoc_dir = 'rdoc' - rdoc.title = "#{name} #{version}" - rdoc.rdoc_files.include('README*') - rdoc.rdoc_files.include('lib/**/*.rb') -end - -desc "Open an irb session preloaded with this library" -task :console do - sh "irb -rubygems -r ./lib/#{name}.rb" -end - -############################################################################# -# -# Custom tasks (add your own tasks here) -# -############################################################################# - - - -############################################################################# -# -# Packaging tasks -# -############################################################################# - -task :release => :build do - unless `git branch` =~ /^\* master$/ - puts "You must be on the master branch to release!" - exit! - end - sh "git commit --allow-empty -a -m 'Release #{version}'" - sh "git tag v#{version}" - sh "git push origin master" - sh "git push v#{version}" - sh "gem push pkg/#{name}-#{version}.gem" -end - -task :build => :gemspec do - sh "mkdir -p pkg" - sh "gem build #{gemspec_file}" - sh "mv #{gem_file} pkg" -end - -task :gemspec => :validate do - # read spec file and split out manifest section - spec = File.read(gemspec_file) - head, manifest, tail = spec.split(" # = MANIFEST =\n") - - # replace name version and date - replace_header(head, :name) - replace_header(head, :version) - replace_header(head, :date) - #comment this out if your rubyforge_project has a different name - replace_header(head, :rubyforge_project) - - # determine file list from git ls-files - files = `git ls-files`. - split("\n"). - sort. - reject { |file| file =~ /^\./ }. - reject { |file| file =~ /^(rdoc|pkg)/ }. - map { |file| " #{file}" }. - join("\n") - - # piece file back together and write - manifest = " s.files = %w[\n#{files}\n ]\n" - spec = [head, manifest, tail].join(" # = MANIFEST =\n") - File.open(gemspec_file, 'w') { |io| io.write(spec) } - puts "Updated #{gemspec_file}" -end - -task :validate do - libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"] - unless libfiles.empty? - puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir." - exit! - end - unless Dir['VERSION*'].empty? - puts "A `VERSION` file at root level violates Gem best practices." - exit! - end -end \ No newline at end of file diff --git a/vendor/plugins/acts_as_versioned/acts_as_versioned.gemspec b/vendor/plugins/acts_as_versioned/acts_as_versioned.gemspec deleted file mode 100644 index 25d27c7..0000000 --- a/vendor/plugins/acts_as_versioned/acts_as_versioned.gemspec +++ /dev/null @@ -1,85 +0,0 @@ -## This is the rakegem gemspec template. Make sure you read and understand -## all of the comments. Some sections require modification, and others can -## be deleted if you don't need them. Once you understand the contents of -## this file, feel free to delete any comments that begin with two hash marks. -## You can find comprehensive Gem::Specification documentation, at -## http://docs.rubygems.org/read/chapter/20 -Gem::Specification.new do |s| - s.specification_version = 2 if s.respond_to? :specification_version= - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.rubygems_version = '1.3.5' - - ## Leave these as is they will be modified for you by the rake gemspec task. - ## If your rubyforge_project name is different, then edit it and comment out - ## the sub! line in the Rakefile - s.name = 'acts_as_versioned' - s.version = '0.6.0' - s.date = '2010-07-19' - s.rubyforge_project = 'acts_as_versioned' - - ## Make sure your summary is short. The description may be as long - ## as you like. - s.summary = "Add simple versioning to ActiveRecord models." - s.description = "Add simple versioning to ActiveRecord models." - - ## List the primary authors. If there are a bunch of authors, it's probably - ## better to set the email to an email list or something. If you don't have - ## a custom homepage, consider using your GitHub URL or the like. - s.authors = ["Rick Olson"] - s.email = 'technoweenie@gmail.com' - s.homepage = 'http://github.com/technoweenie/acts_as_versioned' - - ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as - ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb' - s.require_paths = %w[lib] - - ## Specify any RDoc options here. You'll want to add your README and - ## LICENSE files to the extra_rdoc_files list. - s.rdoc_options = ["--charset=UTF-8"] - s.extra_rdoc_files = %w[README MIT-LICENSE CHANGELOG] - - ## List your runtime dependencies here. Runtime dependencies are those - ## that are needed for an end user to actually USE your code. - s.add_dependency('activerecord', [">= 3.1.0"]) - - ## List your development dependencies here. Development dependencies are - ## those that are only needed during development - s.add_development_dependency('sqlite3-ruby', ["~> 1.3.1"]) - - ## Leave this section as-is. It will be automatically generated from the - ## contents of your Git repository via the gemspec task. DO NOT REMOVE - ## THE MANIFEST COMMENTS, they are used as delimiters by the task. - # = MANIFEST = - s.files = %w[ - CHANGELOG - Gemfile - MIT-LICENSE - README - RUNNING_UNIT_TESTS - Rakefile - acts_as_versioned.gemspec - init.rb - lib/acts_as_versioned.rb - test/abstract_unit.rb - test/database.yml - test/fixtures/authors.yml - test/fixtures/landmark.rb - test/fixtures/landmark_versions.yml - test/fixtures/landmarks.yml - test/fixtures/locked_pages.yml - test/fixtures/locked_pages_revisions.yml - test/fixtures/migrations/1_add_versioned_tables.rb - test/fixtures/page.rb - test/fixtures/page_versions.yml - test/fixtures/pages.yml - test/fixtures/widget.rb - test/migration_test.rb - test/schema.rb - test/versioned_test.rb - ] - # = MANIFEST = - - ## Test files will be grabbed from the file list. Make sure the path glob - ## matches what you actually use. - s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ } -end diff --git a/vendor/plugins/acts_as_versioned/init.rb b/vendor/plugins/acts_as_versioned/init.rb deleted file mode 100644 index db5f1c4..0000000 --- a/vendor/plugins/acts_as_versioned/init.rb +++ /dev/null @@ -1 +0,0 @@ -require File.join(File.dirname(__FILE__), 'lib', 'acts_as_versioned') \ No newline at end of file diff --git a/vendor/plugins/acts_as_versioned/lib/acts_as_versioned.rb b/vendor/plugins/acts_as_versioned/lib/acts_as_versioned.rb deleted file mode 100644 index 6356dd2..0000000 --- a/vendor/plugins/acts_as_versioned/lib/acts_as_versioned.rb +++ /dev/null @@ -1,494 +0,0 @@ -# Copyright (c) 2005 Rick Olson -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -require 'active_support/concern' - -module ActiveRecord #:nodoc: - module Acts #:nodoc: - # Specify this act if you want to save a copy of the row in a versioned table. This assumes there is a - # versioned table ready and that your model has a version field. This works with optimistic locking if the lock_version - # column is present as well. - # - # The class for the versioned model is derived the first time it is seen. Therefore, if you change your database schema you have to restart - # your container for the changes to be reflected. In development mode this usually means restarting WEBrick. - # - # class Page < ActiveRecord::Base - # # assumes pages_versions table - # acts_as_versioned - # end - # - # Example: - # - # page = Page.create(:title => 'hello world!') - # page.version # => 1 - # - # page.title = 'hello world' - # page.save - # page.version # => 2 - # page.versions.size # => 2 - # - # page.revert_to(1) # using version number - # page.title # => 'hello world!' - # - # page.revert_to(page.versions.last) # using versioned instance - # page.title # => 'hello world' - # - # page.versions.earliest # efficient query to find the first version - # page.versions.latest # efficient query to find the most recently created version - # - # - # Simple Queries to page between versions - # - # page.versions.before(version) - # page.versions.after(version) - # - # Access the previous/next versions from the versioned model itself - # - # version = page.versions.latest - # version.previous # go back one version - # version.next # go forward one version - # - # See ActiveRecord::Acts::Versioned::ClassMethods#acts_as_versioned for configuration options - module Versioned - VERSION = "0.6.0" - CALLBACKS = [:set_new_version, :save_version, :save_version?] - - # == Configuration options - # - # * class_name - versioned model class name (default: PageVersion in the above example) - # * table_name - versioned model table name (default: page_versions in the above example) - # * foreign_key - foreign key used to relate the versioned model to the original model (default: page_id in the above example) - # * inheritance_column - name of the column to save the model's inheritance_column value for STI. (default: versioned_type) - # * version_column - name of the column in the model that keeps the version number (default: version) - # * sequence_name - name of the custom sequence to be used by the versioned model. - # * limit - number of revisions to keep, defaults to unlimited - # * if - symbol of method to check before saving a new version. If this method returns false, a new version is not saved. - # For finer control, pass either a Proc or modify Model#version_condition_met? - # - # acts_as_versioned :if => Proc.new { |auction| !auction.expired? } - # - # or... - # - # class Auction - # def version_condition_met? # totally bypasses the :if option - # !expired? - # end - # end - # - # * if_changed - Simple way of specifying attributes that are required to be changed before saving a model. This takes - # either a symbol or array of symbols. - # - # * extend - Lets you specify a module to be mixed in both the original and versioned models. You can also just pass a block - # to create an anonymous mixin: - # - # class Auction - # acts_as_versioned do - # def started? - # !started_at.nil? - # end - # end - # end - # - # or... - # - # module AuctionExtension - # def started? - # !started_at.nil? - # end - # end - # class Auction - # acts_as_versioned :extend => AuctionExtension - # end - # - # Example code: - # - # @auction = Auction.find(1) - # @auction.started? - # @auction.versions.first.started? - # - # == Database Schema - # - # The model that you're versioning needs to have a 'version' attribute. The model is versioned - # into a table called #{model}_versions where the model name is singlular. The _versions table should - # contain all the fields you want versioned, the same version column, and a #{model}_id foreign key field. - # - # A lock_version field is also accepted if your model uses Optimistic Locking. If your table uses Single Table inheritance, - # then that field is reflected in the versioned model as 'versioned_type' by default. - # - # Acts_as_versioned comes prepared with the ActiveRecord::Acts::Versioned::ActMethods::ClassMethods#create_versioned_table - # method, perfect for a migration. It will also create the version column if the main model does not already have it. - # - # class AddVersions < ActiveRecord::Migration - # def self.up - # # create_versioned_table takes the same options hash - # # that create_table does - # Post.create_versioned_table - # end - # - # def self.down - # Post.drop_versioned_table - # end - # end - # - # == Changing What Fields Are Versioned - # - # By default, acts_as_versioned will version all but these fields: - # - # [self.primary_key, inheritance_column, 'version', 'lock_version', versioned_inheritance_column] - # - # You can add or change those by modifying #non_versioned_columns. Note that this takes strings and not symbols. - # - # class Post < ActiveRecord::Base - # acts_as_versioned - # self.non_versioned_columns << 'comments_count' - # end - # - def acts_as_versioned(options = {}, &extension) - # don't allow multiple calls - return if self.included_modules.include?(ActiveRecord::Acts::Versioned::Behaviors) - - cattr_accessor :versioned_class_name, :versioned_foreign_key, :versioned_table_name, :versioned_inheritance_column, - :version_column, :max_version_limit, :track_altered_attributes, :version_condition, :version_sequence_name, :non_versioned_columns, - :version_association_options, :version_if_changed - - self.versioned_class_name = options[:class_name] || "Version" - self.versioned_foreign_key = options[:foreign_key] || self.to_s.foreign_key - self.versioned_table_name = options[:table_name] || "#{table_name_prefix}#{base_class.name.demodulize.underscore}_versions#{table_name_suffix}" - self.versioned_inheritance_column = options[:inheritance_column] || "versioned_#{inheritance_column}" - self.version_column = options[:version_column] || 'version' - self.version_sequence_name = options[:sequence_name] - self.max_version_limit = options[:limit].to_i - self.version_condition = options[:if] || true - self.non_versioned_columns = [self.primary_key, inheritance_column, self.version_column, 'lock_version', versioned_inheritance_column] + options[:non_versioned_columns].to_a.map(&:to_s) - self.version_association_options = { - :class_name => "#{self.to_s}::#{versioned_class_name}", - :foreign_key => versioned_foreign_key, - :dependent => :delete_all - }.merge(options[:association_options] || {}) - - if block_given? - extension_module_name = "#{versioned_class_name}Extension" - silence_warnings do - self.const_set(extension_module_name, Module.new(&extension)) - end - - options[:extend] = self.const_get(extension_module_name) - end - - unless options[:if_changed].nil? - self.track_altered_attributes = true - options[:if_changed] = [options[:if_changed]] unless options[:if_changed].is_a?(Array) - self.version_if_changed = options[:if_changed].map(&:to_s) - end - - include options[:extend] if options[:extend].is_a?(Module) - - include ActiveRecord::Acts::Versioned::Behaviors - - # - # Create the dynamic versioned model - # - const_set(versioned_class_name, Class.new(ActiveRecord::Base)).class_eval do - def self.reloadable?; - false; - end - - # find first version before the given version - def self.before(version) - where(["#{original_class.versioned_foreign_key} = ? and version < ?", version.send(original_class.versioned_foreign_key), version.version]). - order('version DESC'). - first - end - - # find first version after the given version. - def self.after(version) - where(["#{original_class.versioned_foreign_key} = ? and version > ?", version.send(original_class.versioned_foreign_key), version.version]). - order('version ASC'). - first - end - - # finds earliest version of this record - def self.earliest - order("#{original_class.version_column}").first - end - - # find latest version of this record - def self.latest - order("#{original_class.version_column} desc").first - end - - def previous - self.class.before(self) - end - - def next - self.class.after(self) - end - - def versions_count - page.version - end - end - - versioned_class.cattr_accessor :original_class - versioned_class.original_class = self - versioned_class.set_table_name versioned_table_name - versioned_class.belongs_to self.to_s.demodulize.underscore.to_sym, - :class_name => "::#{self.to_s}", - :foreign_key => versioned_foreign_key - versioned_class.send :include, options[:extend] if options[:extend].is_a?(Module) - versioned_class.set_sequence_name version_sequence_name if version_sequence_name - end - - module Behaviors - extend ActiveSupport::Concern - - included do - has_many :versions, self.version_association_options - - before_save :set_new_version - after_save :save_version - after_save :clear_old_versions - end - - module InstanceMethods - # Saves a version of the model in the versioned table. This is called in the after_save callback by default - def save_version - if @saving_version - @saving_version = nil - rev = self.class.versioned_class.new - clone_versioned_model(self, rev) - rev.send("#{self.class.version_column}=", send(self.class.version_column)) - rev.send("#{self.class.versioned_foreign_key}=", id) - rev.save - end - end - - # Clears old revisions if a limit is set with the :limit option in acts_as_versioned. - # Override this method to set your own criteria for clearing old versions. - def clear_old_versions - return if self.class.max_version_limit == 0 - excess_baggage = send(self.class.version_column).to_i - self.class.max_version_limit - if excess_baggage > 0 - self.class.versioned_class.delete_all ["#{self.class.version_column} <= ? and #{self.class.versioned_foreign_key} = ?", excess_baggage, id] - end - end - - # Reverts a model to a given version. Takes either a version number or an instance of the versioned model - def revert_to(version) - if version.is_a?(self.class.versioned_class) - return false unless version.send(self.class.versioned_foreign_key) == id and !version.new_record? - else - return false unless version = versions.where(self.class.version_column => version).first - end - self.clone_versioned_model(version, self) - send("#{self.class.version_column}=", version.send(self.class.version_column)) - true - end - - # Reverts a model to a given version and saves the model. - # Takes either a version number or an instance of the versioned model - def revert_to!(version) - revert_to(version) ? save_without_revision : false - end - - # Temporarily turns off Optimistic Locking while saving. Used when reverting so that a new version is not created. - def save_without_revision - save_without_revision! - true - rescue - false - end - - def save_without_revision! - without_locking do - without_revision do - save! - end - end - end - - def altered? - track_altered_attributes ? (version_if_changed - changed).length < version_if_changed.length : changed? - end - - # Clones a model. Used when saving a new version or reverting a model's version. - def clone_versioned_model(orig_model, new_model) - self.class.versioned_columns.each do |col| - new_model[col.name] = orig_model.send(col.name) if orig_model.has_attribute?(col.name) - end - - if orig_model.is_a?(self.class.versioned_class) - new_model[new_model.class.inheritance_column] = orig_model[self.class.versioned_inheritance_column] - elsif new_model.is_a?(self.class.versioned_class) - new_model[self.class.versioned_inheritance_column] = orig_model[orig_model.class.inheritance_column] - end - end - - # Checks whether a new version shall be saved or not. Calls version_condition_met? and changed?. - def save_version? - version_condition_met? && altered? - end - - # Checks condition set in the :if option to check whether a revision should be created or not. Override this for - # custom version condition checking. - def version_condition_met? - case - when version_condition.is_a?(Symbol) - send(version_condition) - when version_condition.respond_to?(:call) && (version_condition.arity == 1 || version_condition.arity == -1) - version_condition.call(self) - else - version_condition - end - end - - # Executes the block with the versioning callbacks disabled. - # - # @foo.without_revision do - # @foo.save - # end - # - def without_revision(&block) - self.class.without_revision(&block) - end - - # Turns off optimistic locking for the duration of the block - # - # @foo.without_locking do - # @foo.save - # end - # - def without_locking(&block) - self.class.without_locking(&block) - end - - def empty_callback() - end - - #:nodoc: - - protected - # sets the new version before saving, unless you're using optimistic locking. In that case, let it take care of the version. - def set_new_version - @saving_version = new_record? || save_version? - self.send("#{self.class.version_column}=", next_version) if new_record? || (!locking_enabled? && save_version?) - end - - # Gets the next available version for the current record, or 1 for a new record - def next_version - (new_record? ? 0 : versions.calculate(:maximum, version_column).to_i) + 1 - end - end - - module ClassMethods - # Returns an array of columns that are versioned. See non_versioned_columns - def versioned_columns - @versioned_columns ||= columns.select { |c| !non_versioned_columns.include?(c.name) } - end - - # Returns an instance of the dynamic versioned model - def versioned_class - const_get versioned_class_name - end - - # Rake migration task to create the versioned table using options passed to acts_as_versioned - def create_versioned_table(create_table_options = {}) - # create version column in main table if it does not exist - if !self.content_columns.find { |c| [version_column.to_s, 'lock_version'].include? c.name } - self.connection.add_column table_name, version_column, :integer - self.reset_column_information - end - - return if connection.table_exists?(versioned_table_name) - - self.connection.create_table(versioned_table_name, create_table_options) do |t| - t.column versioned_foreign_key, :integer - t.column version_column, :integer - end - - self.versioned_columns.each do |col| - self.connection.add_column versioned_table_name, col.name, col.type, - :limit => col.limit, - :default => col.default, - :scale => col.scale, - :precision => col.precision - end - - if type_col = self.columns_hash[inheritance_column] - self.connection.add_column versioned_table_name, versioned_inheritance_column, type_col.type, - :limit => type_col.limit, - :default => type_col.default, - :scale => type_col.scale, - :precision => type_col.precision - end - - self.connection.add_index versioned_table_name, versioned_foreign_key - end - - # Rake migration task to drop the versioned table - def drop_versioned_table - self.connection.drop_table versioned_table_name - end - - # Executes the block with the versioning callbacks disabled. - # - # Foo.without_revision do - # @foo.save - # end - # - def without_revision(&block) - class_eval do - CALLBACKS.each do |attr_name| - alias_method "orig_#{attr_name}".to_sym, attr_name - alias_method attr_name, :empty_callback - end - end - block.call - ensure - class_eval do - CALLBACKS.each do |attr_name| - alias_method attr_name, "orig_#{attr_name}".to_sym - end - end - end - - # Turns off optimistic locking for the duration of the block - # - # Foo.without_locking do - # @foo.save - # end - # - def without_locking(&block) - current = ActiveRecord::Base.lock_optimistically - ActiveRecord::Base.lock_optimistically = false if current - begin - block.call - ensure - ActiveRecord::Base.lock_optimistically = true if current - end - end - end - end - end - end -end - -ActiveRecord::Base.extend ActiveRecord::Acts::Versioned diff --git a/vendor/plugins/acts_as_versioned/test/database.yml b/vendor/plugins/acts_as_versioned/test/database.yml deleted file mode 100644 index cef97af..0000000 --- a/vendor/plugins/acts_as_versioned/test/database.yml +++ /dev/null @@ -1,18 +0,0 @@ -sqlite: - adapter: sqlite - dbfile: acts_as_versioned_plugin.sqlite.db -sqlite3: - adapter: sqlite3 - database: acts_as_versioned_plugin.sqlite3.db -postgresql: - adapter: postgresql - username: postgres - password: postgres - database: acts_as_versioned_plugin_test - min_messages: ERROR -mysql: - adapter: mysql - host: localhost - username: rails - password: - database: acts_as_versioned_plugin_test \ No newline at end of file