diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a37ae09a8..87a93c815 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -52,7 +52,7 @@ class ProjectsController < ApplicationController respond_to do |format| format.html { @project_tree = projects.group_by {|p| p.parent || p} - @project_tree.each_key {|p| @project_tree[p] -= [p]} + @project_tree.keys.each {|p| @project_tree[p] -= [p]} } format.atom { render_feed(projects.sort_by(&:created_on).reverse.slice(0, Setting.feeds_limit.to_i), diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index e94ae2e7f..4ef337c26 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -22,6 +22,10 @@ module RepositoriesHelper txt.to_s[0,8] end + def to_path_param(path) + path.to_s.split(%r{[/\\]}).select {|p| !p.blank?} + end + def to_utf8(str) return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii @encodings ||= Setting.repositories_encodings.split(',').collect(&:strip) diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb index 73e4a50c6..3daa7a740 100644 --- a/app/models/user_preference.rb +++ b/app/models/user_preference.rb @@ -42,8 +42,10 @@ class UserPreference < ActiveRecord::Base if attribute_present? attr_name super else - self.others ||= {} - self.others.store attr_name, value + h = read_attribute(:others).dup || {} + h.update(attr_name => value) + write_attribute(:others, h) + value end end diff --git a/app/views/repositories/_dir_list_content.rhtml b/app/views/repositories/_dir_list_content.rhtml index c30216533..20473a264 100644 --- a/app/views/repositories/_dir_list_content.rhtml +++ b/app/views/repositories/_dir_list_content.rhtml @@ -4,14 +4,14 @@ <% if entry.is_dir? %> - "scmEntryClick('#{tr_id}')"%>">  <% end %> <%= link_to h(entry.name), - {:action => (entry.is_dir? ? 'browse' : 'changes'), :id => @project, :path => entry.path, :rev => @rev}, + {:action => (entry.is_dir? ? 'browse' : 'changes'), :id => @project, :path => to_path_param(entry.path), :rev => @rev}, :class => (entry.is_dir? ? 'icon icon-folder' : 'icon icon-file')%> <%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %> diff --git a/app/views/repositories/_navigation.rhtml b/app/views/repositories/_navigation.rhtml index b7ac989bc..25a15f496 100644 --- a/app/views/repositories/_navigation.rhtml +++ b/app/views/repositories/_navigation.rhtml @@ -10,10 +10,10 @@ dirs.each do |dir| link_path << '/' unless link_path.empty? link_path << "#{dir}" %> - / <%= link_to h(dir), :action => 'browse', :id => @project, :path => link_path, :rev => @rev %> + / <%= link_to h(dir), :action => 'browse', :id => @project, :path => to_path_param(link_path), :rev => @rev %> <% end %> <% if filename %> - / <%= link_to h(filename), :action => 'changes', :id => @project, :path => "#{link_path}/#{filename}", :rev => @rev %> + / <%= link_to h(filename), :action => 'changes', :id => @project, :path => to_path_param("#{link_path}/#{filename}"), :rev => @rev %> <% end %> <%= "@ #{revision}" if revision %> diff --git a/app/views/repositories/_revisions.rhtml b/app/views/repositories/_revisions.rhtml index 1bcf0208c..a938fecb8 100644 --- a/app/views/repositories/_revisions.rhtml +++ b/app/views/repositories/_revisions.rhtml @@ -1,4 +1,4 @@ -<% form_tag({:controller => 'repositories', :action => 'diff', :id => @project, :path => path}, :method => :get) do %> +<% form_tag({:controller => 'repositories', :action => 'diff', :id => @project, :path => to_path_param(path)}, :method => :get) do %> diff --git a/app/views/repositories/changes.rhtml b/app/views/repositories/changes.rhtml index 341c6cba5..85695ec45 100644 --- a/app/views/repositories/changes.rhtml +++ b/app/views/repositories/changes.rhtml @@ -4,12 +4,12 @@

<% if @repository.supports_cat? %> - <%= link_to l(:button_view), {:action => 'entry', :id => @project, :path => @path, :rev => @rev } %> | + <%= link_to l(:button_view), {:action => 'entry', :id => @project, :path => to_path_param(@path), :rev => @rev } %> | <% end %> <% if @repository.supports_annotate? %> - <%= link_to l(:button_annotate), {:action => 'annotate', :id => @project, :path => @path, :rev => @rev } %> | + <%= link_to l(:button_annotate), {:action => 'annotate', :id => @project, :path => to_path_param(@path), :rev => @rev } %> | <% end %> -<%= link_to(l(:button_download), {:action => 'entry', :id => @project, :path => @path, :rev => @rev, :format => 'raw' }) if @repository.supports_cat? %> +<%= link_to(l(:button_download), {:action => 'entry', :id => @project, :path => to_path_param(@path), :rev => @rev, :format => 'raw' }) if @repository.supports_cat? %> <%= "(#{number_to_human_size(@entry.size)})" if @entry.size %>

diff --git a/app/views/repositories/revision.rhtml b/app/views/repositories/revision.rhtml index d0ff1de6d..04c0e2108 100644 --- a/app/views/repositories/revision.rhtml +++ b/app/views/repositories/revision.rhtml @@ -55,7 +55,7 @@ <%= "(#{change.revision})" unless change.revision.blank? %> diff --git a/config/boot.rb b/config/boot.rb index 9fcd50fe3..cd21fb9ea 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,19 +1,109 @@ -# Don't change this file. Configuration is done in config/environment.rb and config/environments/*.rb +# Don't change this file! +# Configure your app in config/environment.rb and config/environments/*.rb -unless defined?(RAILS_ROOT) - root_path = File.join(File.dirname(__FILE__), '..') - unless RUBY_PLATFORM =~ /mswin32/ - require 'pathname' - root_path = Pathname.new(root_path).cleanpath(true).to_s +RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT) + +module Rails + class << self + def boot! + unless booted? + preinitialize + pick_boot.run + end + end + + def booted? + defined? Rails::Initializer + end + + def pick_boot + (vendor_rails? ? VendorBoot : GemBoot).new + end + + def vendor_rails? + File.exist?("#{RAILS_ROOT}/vendor/rails") + end + + def preinitialize + load(preinitializer_path) if File.exist?(preinitializer_path) + end + + def preinitializer_path + "#{RAILS_ROOT}/config/preinitializer.rb" + end + end + + class Boot + def run + load_initializer + Rails::Initializer.run(:set_load_path) + end + end + + class VendorBoot < Boot + def load_initializer + require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" + Rails::Initializer.run(:install_gem_spec_stubs) + end + end + + class GemBoot < Boot + def load_initializer + self.class.load_rubygems + load_rails_gem + require 'initializer' + end + + def load_rails_gem + if version = self.class.gem_version + gem 'rails', version + else + gem 'rails' + end + rescue Gem::LoadError => load_error + $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.) + exit 1 + end + + class << self + def rubygems_version + Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion + end + + def gem_version + if defined? RAILS_GEM_VERSION + RAILS_GEM_VERSION + elsif ENV.include?('RAILS_GEM_VERSION') + ENV['RAILS_GEM_VERSION'] + else + parse_gem_version(read_environment_rb) + end + end + + def load_rubygems + require 'rubygems' + + unless rubygems_version >= '0.9.4' + $stderr.puts %(Rails requires RubyGems >= 0.9.4 (you have #{rubygems_version}). Please `gem update --system` and try again.) + exit 1 + end + + rescue LoadError + $stderr.puts %(Rails requires RubyGems >= 0.9.4. Please install RubyGems and try again: http://rubygems.rubyforge.org) + exit 1 + end + + def parse_gem_version(text) + $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/ + end + + private + def read_environment_rb + File.read("#{RAILS_ROOT}/config/environment.rb") + end + end end - RAILS_ROOT = root_path end -if File.directory?("#{RAILS_ROOT}/vendor/rails") - require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" -else - require 'rubygems' - require 'initializer' -end - -Rails::Initializer.run(:set_load_path) +# All that for this: +Rails.boot! diff --git a/config/environment.rb b/config/environment.rb index f09c1009a..b0f16c3e1 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -5,7 +5,7 @@ # ENV['RAILS_ENV'] ||= 'production' # Specifies gem version of Rails to use when vendor/rails is not present -RAILS_GEM_VERSION = '2.0.2' unless defined? RAILS_GEM_VERSION +RAILS_GEM_VERSION = '2.1.0' unless defined? RAILS_GEM_VERSION # Bootstrap the Rails environment, frameworks, and default configuration require File.join(File.dirname(__FILE__), 'boot') @@ -71,32 +71,3 @@ Rails::Initializer.run do |config| config.action_mailer.delivery_method = :smtp end - -ActiveRecord::Errors.default_error_messages = { - :inclusion => "activerecord_error_inclusion", - :exclusion => "activerecord_error_exclusion", - :invalid => "activerecord_error_invalid", - :confirmation => "activerecord_error_confirmation", - :accepted => "activerecord_error_accepted", - :empty => "activerecord_error_empty", - :blank => "activerecord_error_blank", - :too_long => "activerecord_error_too_long", - :too_short => "activerecord_error_too_short", - :wrong_length => "activerecord_error_wrong_length", - :taken => "activerecord_error_taken", - :not_a_number => "activerecord_error_not_a_number" -} - -ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| "#{html_tag}" } - -Mime::SET << Mime::CSV unless Mime::SET.include?(Mime::CSV) -Mime::Type.register 'application/pdf', :pdf - -GLoc.set_config :default_language => :en -GLoc.clear_strings -GLoc.set_kcode -GLoc.load_localized_strings -GLoc.set_config(:raise_string_not_found_errors => false) - -require 'redmine' - diff --git a/config/initializers/10-patches.rb b/config/initializers/10-patches.rb new file mode 100644 index 000000000..fcc091997 --- /dev/null +++ b/config/initializers/10-patches.rb @@ -0,0 +1,17 @@ + +ActiveRecord::Errors.default_error_messages = { + :inclusion => "activerecord_error_inclusion", + :exclusion => "activerecord_error_exclusion", + :invalid => "activerecord_error_invalid", + :confirmation => "activerecord_error_confirmation", + :accepted => "activerecord_error_accepted", + :empty => "activerecord_error_empty", + :blank => "activerecord_error_blank", + :too_long => "activerecord_error_too_long", + :too_short => "activerecord_error_too_short", + :wrong_length => "activerecord_error_wrong_length", + :taken => "activerecord_error_taken", + :not_a_number => "activerecord_error_not_a_number" +} + +ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| "#{html_tag}" } diff --git a/config/initializers/20-mime_types.rb b/config/initializers/20-mime_types.rb new file mode 100644 index 000000000..269742b16 --- /dev/null +++ b/config/initializers/20-mime_types.rb @@ -0,0 +1,4 @@ +# Add new mime types for use in respond_to blocks: + +Mime::SET << Mime::CSV unless Mime::SET.include?(Mime::CSV) +Mime::Type.register 'application/pdf', :pdf diff --git a/config/initializers/30-redmine.rb b/config/initializers/30-redmine.rb new file mode 100644 index 000000000..f2a9f6a30 --- /dev/null +++ b/config/initializers/30-redmine.rb @@ -0,0 +1,7 @@ +GLoc.set_config :default_language => :en +GLoc.clear_strings +GLoc.set_kcode +GLoc.load_localized_strings +GLoc.set_config(:raise_string_not_found_errors => false) + +require 'redmine' diff --git a/db/migrate/072_add_enumerations_position.rb b/db/migrate/072_add_enumerations_position.rb index e0beaf395..22558a6e9 100644 --- a/db/migrate/072_add_enumerations_position.rb +++ b/db/migrate/072_add_enumerations_position.rb @@ -1,7 +1,7 @@ class AddEnumerationsPosition < ActiveRecord::Migration def self.up add_column(:enumerations, :position, :integer, :default => 1) unless Enumeration.column_names.include?('position') - Enumeration.find(:all).group_by(&:opt).each_value do |enums| + Enumeration.find(:all).group_by(&:opt).each do |opt, enums| enums.each_with_index do |enum, i| # do not call model callbacks Enumeration.update_all "position = #{i+1}", {:id => enum.id} diff --git a/db/migrate/078_add_custom_fields_position.rb b/db/migrate/078_add_custom_fields_position.rb index 7ee8abb58..1c42ae732 100644 --- a/db/migrate/078_add_custom_fields_position.rb +++ b/db/migrate/078_add_custom_fields_position.rb @@ -1,7 +1,7 @@ class AddCustomFieldsPosition < ActiveRecord::Migration def self.up add_column(:custom_fields, :position, :integer, :default => 1) - CustomField.find(:all).group_by(&:type).each_value do |fields| + CustomField.find(:all).group_by(&:type).each do |t, fields| fields.each_with_index do |field, i| # do not call model callbacks CustomField.update_all "position = #{i+1}", {:id => field.id} diff --git a/lib/tabular_form_builder.rb b/lib/tabular_form_builder.rb index 5b331fe3f..88e35a6d2 100644 --- a/lib/tabular_form_builder.rb +++ b/lib/tabular_form_builder.rb @@ -22,7 +22,7 @@ class TabularFormBuilder < ActionView::Helpers::FormBuilder def initialize(object_name, object, template, options, proc) set_language_if_valid options.delete(:lang) - @object_name, @object, @template, @options, @proc = object_name, object, template, options, proc + super end (field_helpers - %w(radio_button hidden_field) + %w(date_select)).each do |selector| diff --git a/script/dbconsole b/script/dbconsole new file mode 100644 index 000000000..caa60ce82 --- /dev/null +++ b/script/dbconsole @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +require File.dirname(__FILE__) + '/../config/boot' +require 'commands/dbconsole' diff --git a/script/performance/request b/script/performance/request new file mode 100644 index 000000000..ae3f38c74 --- /dev/null +++ b/script/performance/request @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +require File.dirname(__FILE__) + '/../../config/boot' +require 'commands/performance/request' diff --git a/script/process/inspector b/script/process/inspector new file mode 100644 index 000000000..bf25ad86d --- /dev/null +++ b/script/process/inspector @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +require File.dirname(__FILE__) + '/../../config/boot' +require 'commands/process/inspector' diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 88c0319ba..88a9fae60 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -38,7 +38,7 @@ class ProjectsControllerTest < Test::Unit::TestCase assert_template 'index' assert_not_nil assigns(:project_tree) # Root project as hash key - assert assigns(:project_tree).has_key?(Project.find(1)) + assert assigns(:project_tree).keys.include?(Project.find(1)) # Subproject in corresponding value assert assigns(:project_tree)[Project.find(1)].include?(Project.find(3)) end diff --git a/test/integration/issues_test.rb b/test/integration/issues_test.rb index 1b57ba8f8..2ef933fc2 100644 --- a/test/integration/issues_test.rb +++ b/test/integration/issues_test.rb @@ -20,8 +20,11 @@ require "#{File.dirname(__FILE__)}/../test_helper" class IssuesTest < ActionController::IntegrationTest fixtures :projects, :users, + :roles, + :members, :trackers, :projects_trackers, + :enabled_modules, :issue_statuses, :issues, :enumerations, diff --git a/test/test_helper.rb b/test/test_helper.rb index 1340f9c35..f61b88d8c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -65,20 +65,3 @@ class Test::Unit::TestCase Attachment.storage_path = "#{RAILS_ROOT}/tmp/test/attachments" end end - - -# ActionController::TestUploadedFile bug -# see http://dev.rubyonrails.org/ticket/4635 -class String - def original_filename - "testfile.txt" - end - - def content_type - "text/plain" - end - - def read - self.to_s - end -end diff --git a/test/unit/role_test.rb b/test/unit/role_test.rb index 5e0d16753..b98af2e36 100644 --- a/test/unit/role_test.rb +++ b/test/unit/role_test.rb @@ -26,7 +26,7 @@ class RoleTest < Test::Unit::TestCase target = Role.new(:name => 'Target') assert target.save - assert target.workflows.copy(source) + target.workflows.copy(source) target.reload assert_equal 90, target.workflows.size end diff --git a/test/unit/tracker_test.rb b/test/unit/tracker_test.rb index 406bdd6db..6dab8890c 100644 --- a/test/unit/tracker_test.rb +++ b/test/unit/tracker_test.rb @@ -26,7 +26,7 @@ class TrackerTest < Test::Unit::TestCase target = Tracker.new(:name => 'Target') assert target.save - assert target.workflows.copy(source) + target.workflows.copy(source) target.reload assert_equal 89, target.workflows.size end diff --git a/vendor/plugins/acts_as_versioned/Rakefile b/vendor/plugins/acts_as_versioned/Rakefile index 3ae69e961..5bccb5d8d 100644 --- a/vendor/plugins/acts_as_versioned/Rakefile +++ b/vendor/plugins/acts_as_versioned/Rakefile @@ -1,182 +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 +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/vendor/plugins/acts_as_versioned/lib/acts_as_versioned.rb b/vendor/plugins/acts_as_versioned/lib/acts_as_versioned.rb index 5e6f6e636..bba10c437 100644 --- a/vendor/plugins/acts_as_versioned/lib/acts_as_versioned.rb +++ b/vendor/plugins/acts_as_versioned/lib/acts_as_versioned.rb @@ -22,7 +22,7 @@ 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 optimisic locking if the lock_version + # 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 @@ -49,9 +49,24 @@ module ActiveRecord #:nodoc: # 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_changed_attributes] + CALLBACKS = [:set_new_version, :save_version_on_create, :save_version?, :clear_altered_attributes] def self.included(base) # :nodoc: base.extend ClassMethods end @@ -80,7 +95,7 @@ module ActiveRecord #:nodoc: # 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. + # 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) @@ -133,7 +148,7 @@ module ActiveRecord #:nodoc: # # that create_table does # Post.create_versioned_table # end - # + # # def self.down # Post.drop_versioned_table # end @@ -157,11 +172,11 @@ module ActiveRecord #:nodoc: 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_changed_attributes, :version_condition, :version_sequence_name, :non_versioned_columns, + :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= @@ -171,7 +186,7 @@ module ActiveRecord #:nodoc: alias_method :non_versioned_fields=, :non_versioned_columns= end - send :attr_accessor, :changed_attributes + 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 @@ -184,8 +199,7 @@ module ActiveRecord #:nodoc: 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}", - :order => 'version', + :foreign_key => versioned_foreign_key, :dependent => :delete_all }.merge(options[:association_options] || {}) @@ -194,20 +208,30 @@ module ActiveRecord #:nodoc: 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 + has_many :versions, version_association_options do + # finds earliest version of this record + def earliest + @earliest ||= find(:first, :order => 'version') + end + + # find latest version of this record + def latest + @latest ||= find(:first, :order => 'version desc') + 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_changed_attributes - + after_save :clear_altered_attributes + unless options[:if_changed].nil? - self.track_changed_attributes = true + 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| @@ -215,15 +239,40 @@ module ActiveRecord #:nodoc: 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) + find :first, :order => 'version desc', + :conditions => ["#{original_class.versioned_foreign_key} = ? and version < ?", version.send(original_class.versioned_foreign_key), version.version] + end + + # find first version after the given version. + def self.after(version) + find :first, :order => 'version', + :conditions => ["#{original_class.versioned_foreign_key} = ? and version > ?", version.send(original_class.versioned_foreign_key), version.version] + 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}", @@ -232,17 +281,22 @@ module ActiveRecord #:nodoc: 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 @@ -263,16 +317,8 @@ module ActiveRecord #:nodoc: end end - # Finds a specific version of this model. - def find_version(version) - return version if version.is_a?(self.class.versioned_class) - return nil if version.is_a?(ActiveRecord::Base) - find_versions(:conditions => ['version = ?', version], :limit => 1).first - end - - # Finds versions of this model. Takes an options hash like find - def find_versions(options = {}) - versions.find(:all, options) + def versions_count + version end # Reverts a model to a given version. Takes either a version number or an instance of the versioned model @@ -280,14 +326,14 @@ module ActiveRecord #:nodoc: 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 = find_version(version) + 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. + # 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 @@ -313,36 +359,36 @@ module ActiveRecord #:nodoc: 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_changed_attributes || (changed_attributes && changed_attributes.length > 0)) : - (changed_attributes && changed_attributes.include?(attr_name.to_s)) + (!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.attributes[key]) if orig_model.has_attribute?(key) + new_model.send("#{key}=", orig_model.send(key)) if orig_model.has_attribute?(key) 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? && 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? @@ -353,7 +399,7 @@ module ActiveRecord #:nodoc: version_condition.call(self) else version_condition - end + end end # Executes the block with the versioning callbacks disabled. @@ -378,43 +424,45 @@ module ActiveRecord #:nodoc: def empty_callback() end #:nodoc: - protected + 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.calculate(:max, :version) || 0) + 1 end - + # clears current changed attributes. Called after save. - def clear_changed_attributes - self.changed_attributes = [] + 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(attr_value) - (self.changed_attributes ||= []) << attr_name.to_s unless self.changed?(attr_name) || self.send(attr_name) == attr_value_for_db + (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 - private - CALLBACKS.each do |attr_name| - alias_method "orig_#{attr_name}".to_sym, attr_name - end - module ClassMethods # Finds a specific version of a specific row of this model - def find_version(id, version) - find_versions(id, - :conditions => ["#{versioned_foreign_key} = ? AND version = ?", id, version], - :limit => 1).first + 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.find :all, { @@ -426,7 +474,7 @@ module ActiveRecord #:nodoc: 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 @@ -438,36 +486,40 @@ module ActiveRecord #:nodoc: 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 + :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 + :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 @@ -476,17 +528,18 @@ module ActiveRecord #:nodoc: # def without_revision(&block) class_eval do - CALLBACKS.each do |attr_name| + CALLBACKS.each do |attr_name| + alias_method "orig_#{attr_name}".to_sym, attr_name alias_method attr_name, :empty_callback end end - result = block.call + block.call + ensure class_eval do CALLBACKS.each do |attr_name| alias_method attr_name, "orig_#{attr_name}".to_sym end end - result end # Turns off optimistic locking for the duration of the block @@ -501,7 +554,7 @@ module ActiveRecord #:nodoc: result = block.call ActiveRecord::Base.lock_optimistically = true if current result - end + end end end end diff --git a/vendor/plugins/acts_as_versioned/test/abstract_unit.rb b/vendor/plugins/acts_as_versioned/test/abstract_unit.rb index 1740db8dc..86f50620c 100644 --- a/vendor/plugins/acts_as_versioned/test/abstract_unit.rb +++ b/vendor/plugins/acts_as_versioned/test/abstract_unit.rb @@ -1,12 +1,21 @@ +$:.unshift(File.dirname(__FILE__) + '/../../../rails/activesupport/lib') +$:.unshift(File.dirname(__FILE__) + '/../../../rails/activerecord/lib') $:.unshift(File.dirname(__FILE__) + '/../lib') - require 'test/unit' -require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb')) -require 'active_record/fixtures' +begin + 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')) ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log") -ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite']) +ActiveRecord::Base.configurations = {'test' => config[ENV['DB'] || 'sqlite3']} +ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) load(File.dirname(__FILE__) + "/schema.rb") @@ -19,17 +28,9 @@ if ENV['DB'] == 'postgresql' end Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/" -$LOAD_PATH.unshift(Test::Unit::TestCase.fixture_path) +$:.unshift(Test::Unit::TestCase.fixture_path) class Test::Unit::TestCase #:nodoc: - def create_fixtures(*table_names) - if block_given? - Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names) { yield } - else - Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names) - end - end - # Turn off transactional fixtures if you're working with MyISAM tables in MySQL self.use_transactional_fixtures = true diff --git a/vendor/plugins/acts_as_versioned/test/fixtures/widget.rb b/vendor/plugins/acts_as_versioned/test/fixtures/widget.rb index 3c38f2fcf..086ac2b40 100644 --- a/vendor/plugins/acts_as_versioned/test/fixtures/widget.rb +++ b/vendor/plugins/acts_as_versioned/test/fixtures/widget.rb @@ -1,6 +1,6 @@ class Widget < ActiveRecord::Base acts_as_versioned :sequence_name => 'widgets_seq', :association_options => { - :dependent => nil, :order => 'version desc' + :dependent => :nullify, :order => 'version desc' } non_versioned_columns << 'foo' end \ No newline at end of file diff --git a/vendor/plugins/acts_as_versioned/test/migration_test.rb b/vendor/plugins/acts_as_versioned/test/migration_test.rb index d85e95883..4ead4a8fe 100644 --- a/vendor/plugins/acts_as_versioned/test/migration_test.rb +++ b/vendor/plugins/acts_as_versioned/test/migration_test.rb @@ -9,9 +9,14 @@ if ActiveRecord::Base.connection.supports_migrations? class MigrationTest < Test::Unit::TestCase self.use_transactional_fixtures = false def teardown - ActiveRecord::Base.connection.initialize_schema_information - ActiveRecord::Base.connection.update "UPDATE schema_info SET version = 0" - + if ActiveRecord::Base.connection.respond_to?(:initialize_schema_information) + ActiveRecord::Base.connection.initialize_schema_information + ActiveRecord::Base.connection.update "UPDATE schema_info SET version = 0" + else + ActiveRecord::Base.connection.initialize_schema_migrations_table + ActiveRecord::Base.connection.assume_migrated_upto_version(0) + end + Thing.connection.drop_table "things" rescue nil Thing.connection.drop_table "thing_versions" rescue nil Thing.reset_column_information @@ -21,8 +26,17 @@ if ActiveRecord::Base.connection.supports_migrations? assert_raises(ActiveRecord::StatementInvalid) { Thing.create :title => 'blah blah' } # take 'er up ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/') - t = Thing.create :title => 'blah blah' + t = Thing.create :title => 'blah blah', :price => 123.45, :type => 'Thing' assert_equal 1, t.versions.size + + # check that the price column has remembered its value correctly + assert_equal t.price, t.versions.first.price + assert_equal t.title, t.versions.first.title + assert_equal t[:type], t.versions.first[:type] + + # make sure that the precision of the price column has been preserved + assert_equal 7, Thing::Version.columns.find{|c| c.name == "price"}.precision + assert_equal 2, Thing::Version.columns.find{|c| c.name == "price"}.scale # now lets take 'er back down ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/') diff --git a/vendor/plugins/acts_as_versioned/test/versioned_test.rb b/vendor/plugins/acts_as_versioned/test/versioned_test.rb index c1e1a4b98..a7bc2082b 100644 --- a/vendor/plugins/acts_as_versioned/test/versioned_test.rb +++ b/vendor/plugins/acts_as_versioned/test/versioned_test.rb @@ -4,9 +4,10 @@ require File.join(File.dirname(__FILE__), 'fixtures/widget') 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 def test_saves_versioned_copy - p = Page.create :title => 'first title', :body => 'first body' + p = Page.create! :title => 'first title', :body => 'first body' assert !p.new_record? assert_equal 1, p.versions.size assert_equal 1, p.version @@ -16,13 +17,13 @@ class VersionedTest < Test::Unit::TestCase def test_saves_without_revision p = pages(:welcome) old_versions = p.versions.count - + p.save_without_revision - + p.without_revision do p.update_attributes :title => 'changed' end - + assert_equal old_versions, p.versions.count end @@ -30,7 +31,7 @@ class VersionedTest < Test::Unit::TestCase p = pages(:welcome) assert_equal 24, p.version assert_equal 'Welcome to the weblog', p.title - + 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 @@ -57,56 +58,56 @@ class VersionedTest < Test::Unit::TestCase p = pages(:welcome) assert_equal 24, p.version assert_equal 'Welcome to the weblog', p.title - + 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 - + def test_rollback_fails_with_invalid_revision p = locked_pages(:welcome) assert !p.revert_to!(locked_pages(:thinking)) end def test_saves_versioned_copy_with_options - p = LockedPage.create :title => 'first title' + p = LockedPage.create! :title => 'first title' assert !p.new_record? assert_equal 1, p.versions.size assert_instance_of LockedPage.versioned_class, p.versions.first end - + def test_rollback_with_version_number_with_options p = locked_pages(:welcome) assert_equal 'Welcome to the weblog', p.title assert_equal 'LockedPage', p.versions.first.version_type - + 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 - + def test_rollback_with_version_class_with_options p = locked_pages(:welcome) assert_equal 'Welcome to the weblog', p.title assert_equal 'LockedPage', p.versions.first.version_type - + assert p.revert_to!(p.versions.first), "Couldn't revert to 1" assert_equal 'Welcome to the weblg', p.title assert_equal 'LockedPage', p.versions.first.version_type end - + def test_saves_versioned_copy_with_sti - p = SpecialLockedPage.create :title => 'first title' + p = SpecialLockedPage.create! :title => 'first title' assert !p.new_record? assert_equal 1, p.versions.size assert_instance_of LockedPage.versioned_class, p.versions.first assert_equal 'SpecialLockedPage', p.versions.first.version_type end - + def test_rollback_with_version_number_with_sti p = locked_pages(:thinking) assert_equal 'So I was thinking', p.title - + 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 @@ -115,11 +116,11 @@ class VersionedTest < Test::Unit::TestCase def test_lock_version_works_with_versioning p = locked_pages(:thinking) p2 = LockedPage.find(p.id) - + p.title = 'fresh title' p.save assert_equal 2, p.versions.size # limit! - + assert_raises(ActiveRecord::StaleObjectError) do p2.title = 'stale title' p2.save @@ -127,15 +128,15 @@ class VersionedTest < Test::Unit::TestCase end def test_version_if_condition - p = Page.create :title => "title" + p = Page.create! :title => "title" assert_equal 1, p.version - + Page.feeling_good = false p.save assert_equal 1, p.version Page.feeling_good = true end - + def test_version_if_condition2 # set new if condition Page.class_eval do @@ -143,46 +144,46 @@ class VersionedTest < Test::Unit::TestCase alias_method :old_feeling_good, :feeling_good? alias_method :feeling_good?, :new_feeling_good end - - p = Page.create :title => "title" + + p = Page.create! :title => "title" assert_equal 1, p.version # version does not increment 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(true).size - + p.update_attributes(:title => 'a title') assert_equal 2, p.version assert_equal 2, p.versions(true).size - + # reset original if condition Page.class_eval { alias_method :feeling_good?, :old_feeling_good } end - + def test_version_if_condition_with_block # set new if condition old_condition = Page.version_condition Page.version_condition = Proc.new { |page| page.title[0..0] == 'b' } - - p = Page.create :title => "title" + + p = Page.create! :title => "title" assert_equal 1, p.version # version does not increment 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(true).size - + p.update_attributes(:title => 'b title') assert_equal 2, p.version assert_equal 2, p.versions(true).size - + # reset original if condition Page.version_condition = old_condition end def test_version_no_limit - p = Page.create :title => "title", :body => 'first body' + p = Page.create! :title => "title", :body => 'first body' p.save p.save 5.times do |i| @@ -191,7 +192,7 @@ class VersionedTest < Test::Unit::TestCase end def test_version_max_limit - p = LockedPage.create :title => "title" + p = LockedPage.create! :title => "title" p.update_attributes(:title => "title1") p.update_attributes(:title => "title2") 5.times do |i| @@ -199,31 +200,29 @@ class VersionedTest < Test::Unit::TestCase assert p.versions(true).size <= 2, "locked version can only store 2 versions" end end - - def test_track_changed_attributes_default_value - assert !Page.track_changed_attributes - assert LockedPage.track_changed_attributes - assert SpecialLockedPage.track_changed_attributes + + def test_track_altered_attributes_default_value + assert !Page.track_altered_attributes + assert LockedPage.track_altered_attributes + 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 - assert_equal 23, pages(:welcome).find_versions.first.version - assert_equal 24, pages(:welcome).find_versions.last.version end - - def test_track_changed_attributes - p = LockedPage.create :title => "title" + + def test_track_altered_attributes + p = LockedPage.create! :title => "title" assert_equal 1, p.lock_version assert_equal 1, p.versions(true).size - + p.title = 'title' assert !p.save_version? p.save assert_equal 2, p.lock_version # still increments version because of optimistic locking assert_equal 1, p.versions(true).size - + p.title = 'updated title' assert p.save_version? p.save @@ -236,27 +235,38 @@ class VersionedTest < Test::Unit::TestCase assert_equal 4, p.lock_version 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 2, locked_pages(:welcome).versions.size - assert_equal 1, locked_pages(:welcome).find_versions(:conditions => ['title LIKE ?', '%weblog%']).length - assert_equal 2, locked_pages(:welcome).find_versions(:conditions => ['title LIKE ?', '%web%']).length - assert_equal 0, locked_pages(:thinking).find_versions(:conditions => ['title LIKE ?', '%web%']).length - assert_equal 2, locked_pages(:welcome).find_versions.length + 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), 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 assert_equal 'widgets_seq', Widget.versioned_class.sequence_name - Widget.create :name => 'new widget' - Widget.create :name => 'new widget' - Widget.create :name => 'new widget' + 3.times { Widget.create! :name => 'new widget' } assert_equal 3, Widget.count assert_equal 3, Widget.versioned_class.count end @@ -268,26 +278,26 @@ class VersionedTest < Test::Unit::TestCase def test_has_many_through_with_custom_association assert_equal [authors(:caged), authors(:mly)], pages(:welcome).revisors end - + def test_referential_integrity pages(:welcome).destroy assert_equal 0, Page.count assert_equal 0, Page::Version.count end - + def test_association_options 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 - assert_nil options[:dependent] + assert_equal :nullify, options[:dependent] assert_equal 'version desc', options[:order] assert_equal 'widget_id', options[:foreign_key] - - widget = Widget.create :name => 'new widget' + + widget = Widget.create! :name => 'new widget' assert_equal 1, Widget.count assert_equal 1, Widget.versioned_class.count widget.destroy @@ -300,14 +310,38 @@ class VersionedTest < Test::Unit::TestCase page_version = page.versions.last assert_equal page, page_version.page end - - def test_unchanged_attributes - landmarks(:washington).attributes = landmarks(:washington).attributes + + def test_unaltered_attributes + landmarks(:washington).attributes = landmarks(:washington).attributes.except("id") assert !landmarks(:washington).changed? end - + def test_unchanged_string_attributes - landmarks(:washington).attributes = landmarks(:washington).attributes.inject({}) { |params, (key, value)| params.update key => value.to_s } + landmarks(:washington).attributes = landmarks(:washington).attributes.except("id").inject({}) { |params, (key, value)| params.update(key => value.to_s) } assert !landmarks(:washington).changed? end -end + + def test_should_find_earliest_version + assert_equal page_versions(:welcome_1), pages(:welcome).versions.earliest + end + + def test_should_find_latest_version + assert_equal page_versions(:welcome_2), pages(:welcome).versions.latest + end + + def test_should_find_previous_version + assert_equal page_versions(:welcome_1), page_versions(:welcome_2).previous + assert_equal page_versions(:welcome_1), pages(:welcome).versions.before(page_versions(:welcome_2)) + end + + def test_should_find_next_version + assert_equal page_versions(:welcome_2), page_versions(:welcome_1).next + assert_equal page_versions(:welcome_2), pages(:welcome).versions.after(page_versions(:welcome_1)) + end + + def test_should_find_version_count + 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/rfpdf/init.rb b/vendor/plugins/rfpdf/init.rb index 7e51d9eba..339bacfdb 100644 --- a/vendor/plugins/rfpdf/init.rb +++ b/vendor/plugins/rfpdf/init.rb @@ -1,3 +1,9 @@ require 'rfpdf' -ActionView::Base::register_template_handler 'rfpdf', RFPDF::View \ No newline at end of file +begin + ActionView::Template::register_template_handler 'rfpdf', RFPDF::View +rescue NameError + # Rails < 2.1 + RFPDF::View.backward_compatibility_mode = true + ActionView::Base::register_template_handler 'rfpdf', RFPDF::View +end diff --git a/vendor/plugins/rfpdf/lib/rfpdf/view.rb b/vendor/plugins/rfpdf/lib/rfpdf/view.rb index 185811202..6b6267331 100644 --- a/vendor/plugins/rfpdf/lib/rfpdf/view.rb +++ b/vendor/plugins/rfpdf/lib/rfpdf/view.rb @@ -30,6 +30,8 @@ module RFPDF class View + @@backward_compatibility_mode = false + cattr_accessor :backward_compatibility_mode def initialize(action_view) @action_view = action_view @@ -45,6 +47,14 @@ module RFPDF :temp_dir => "#{File.expand_path(RAILS_ROOT)}/tmp" }.merge(@action_view.controller.instance_eval{ @options_for_rfpdf } || {}).with_indifferent_access end + + def self.compilable? + false + end + + def compilable? + self.class.compilable? + end def render(template, local_assigns = {}) @pdf_name = "Default.pdf" if @pdf_name.nil? @@ -66,7 +76,7 @@ module RFPDF local_assigns.each do |key,val| class << self; self; end.send(:define_method,key){ val } end - ERB.new(template).result(binding) + ERB.new(@@backward_compatibility_mode == true ? template : template.source).result(binding) end end
# <% if change.action == "M" %> -<%= link_to l(:label_view_diff), :action => 'diff', :id => @project, :path => without_leading_slash(change.relative_path), :rev => @changeset.revision %> +<%= link_to l(:label_view_diff), :action => 'diff', :id => @project, :path => to_path_param(change.relative_path), :rev => @changeset.revision %> <% end %>