From a150689be9281f3a814cd5bdedd42f80f431fe41 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Mon, 19 Oct 2009 00:07:37 +0000 Subject: [PATCH] Improved Project#copy to copy more data from the source Project. #3367 * Versions * Associate the copied issues with the new versions * Wiki * WikiPages * WikiContents * IssueCategories git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2934 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/project.rb | 34 +++++++++++++ test/exemplars/user_exemplar.rb | 2 +- test/exemplars/version_exemplar.rb | 10 ++++ test/test_helper.rb | 13 +++++ test/unit/project_test.rb | 82 +++++++++++++++++++++++++++++- 5 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 test/exemplars/version_exemplar.rb diff --git a/app/models/project.rb b/app/models/project.rb index 74d8a32c24..33ed3b7fa8 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -348,10 +348,44 @@ class Project < ActiveRecord::Base project = project.is_a?(Project) ? project : Project.find(project) Project.transaction do + # Wikis + self.wiki = Wiki.new(project.wiki.attributes.dup.except("project_id")) + project.wiki.pages.each do |page| + new_wiki_content = WikiContent.new(page.content.attributes.dup.except("page_id")) + new_wiki_page = WikiPage.new(page.attributes.dup.except("wiki_id")) + new_wiki_page.content = new_wiki_content + + self.wiki.pages << new_wiki_page + end + + # Versions + project.versions.each do |version| + new_version = Version.new + new_version.attributes = version.attributes.dup.except("project_id") + self.versions << new_version + end + + project.issue_categories.each do |issue_category| + new_issue_category = IssueCategory.new + new_issue_category.attributes = issue_category.attributes.dup.except("project_id") + self.issue_categories << new_issue_category + end + # Issues project.issues.each do |issue| new_issue = Issue.new new_issue.copy_from(issue) + # Reassign fixed_versions by name, since names are unique per + # project and the versions for self are not yet saved + if issue.fixed_version + new_issue.fixed_version = self.versions.select {|v| v.name == issue.fixed_version.name}.first + end + # Reassign the category by name, since names are unique per + # project and the categories for self are not yet saved + if issue.category + new_issue.category = self.issue_categories.select {|c| c.name == issue.category.name}.first + end + self.issues << new_issue end diff --git a/test/exemplars/user_exemplar.rb b/test/exemplars/user_exemplar.rb index d88f5fe7df..154b16d8f9 100644 --- a/test/exemplars/user_exemplar.rb +++ b/test/exemplars/user_exemplar.rb @@ -1,4 +1,4 @@ -class User < ActiveRecord::Base +class User < Principal generator_for :login, :method => :next_email generator_for :mail, :method => :next_email generator_for :firstname, :method => :next_firstname diff --git a/test/exemplars/version_exemplar.rb b/test/exemplars/version_exemplar.rb new file mode 100644 index 0000000000..8aef99f4b4 --- /dev/null +++ b/test/exemplars/version_exemplar.rb @@ -0,0 +1,10 @@ +class Version < ActiveRecord::Base + generator_for :name, :method => :next_name + + def self.next_name + @last_name ||= 'Version 1.0.0' + @last_name.succ! + @last_name + end + +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 308b43097b..37f8bfd00b 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -21,6 +21,19 @@ require 'test_help' require File.expand_path(File.dirname(__FILE__) + '/helper_testcase') require File.join(RAILS_ROOT,'test', 'mocks', 'open_id_authentication_mock.rb') +# TODO: The gem or official version of ObjectDaddy doesn't set +# protected attributes so they need to be wrapped. +def User.generate_with_protected!(attributes={}) + user = User.spawn(attributes) do |user| + user.login = User.next_login + attributes.each do |attr,v| + user.send("#{attr}=", v) + end + end + user.save! + user +end + class ActiveSupport::TestCase # Transactional fixtures accelerate your tests by wrapping each test method # in a transaction that's rolled back on completion. This ensures that the diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb index cd4be20e8c..2ace065ab0 100644 --- a/test/unit/project_test.rb +++ b/test/unit/project_test.rb @@ -290,7 +290,7 @@ class ProjectTest < ActiveSupport::TestCase assert_equal 1, copied_project.status end - context "#copy" do + context "Project#copy" do setup do ProjectCustomField.destroy_all # Custom values are a mess to isolate in tests Project.destroy_all :identifier => "copy-test" @@ -313,6 +313,25 @@ class ProjectTest < ActiveSupport::TestCase end end + should "change the new issues to use the copied version" do + assigned_version = Version.generate!(:name => "Assigned Issues") + @source_project.versions << assigned_version + assert_equal 1, @source_project.versions.size + @source_project.issues << Issue.generate!(:fixed_version_id => assigned_version.id, + :subject => "change the new issues to use the copied version", + :tracker_id => 1, + :project_id => @source_project.id) + + assert @project.copy(@source_project) + @project.reload + copied_issue = @project.issues.first(:conditions => {:subject => "change the new issues to use the copied version"}) + + assert copied_issue + assert copied_issue.fixed_version + assert_equal "Assigned Issues", copied_issue.fixed_version.name # Same name + assert_not_equal assigned_version.id, copied_issue.fixed_version.id # Different record + end + should "copy members" do assert @project.valid? assert @project.members.empty? @@ -337,6 +356,67 @@ class ProjectTest < ActiveSupport::TestCase end end + should "copy versions" do + @source_project.versions << Version.generate! + @source_project.versions << Version.generate! + + assert @project.versions.empty? + assert @project.copy(@source_project) + + assert_equal @source_project.versions.size, @project.versions.size + @project.versions.each do |version| + assert version + assert_equal @project, version.project + end + end + + should "copy wiki" do + assert @project.copy(@source_project) + + assert @project.wiki + assert_not_equal @source_project.wiki, @project.wiki + assert_equal "Start page", @project.wiki.start_page + end + + should "copy wiki pages and content" do + assert @project.copy(@source_project) + + assert @project.wiki + assert_equal 1, @project.wiki.pages.length + + @project.wiki.pages.each do |wiki_page| + assert wiki_page.content + assert !@source_project.wiki.pages.include?(wiki_page) + end + end + + should "copy custom fields" + + should "copy issue categories" do + assert @project.copy(@source_project) + + assert_equal 2, @project.issue_categories.size + @project.issue_categories.each do |issue_category| + assert !@source_project.issue_categories.include?(issue_category) + end + end + + should "change the new issues to use the copied issue categories" do + issue = Issue.find(4) + issue.update_attribute(:category_id, 3) + + assert @project.copy(@source_project) + + @project.issues.each do |issue| + assert issue.category + assert_equal "Stock management", issue.category.name # Same name + assert_not_equal IssueCategory.find(3), issue.category # Different record + end + end + + should "copy issue relations" + should "link issue relations if cross project issue relations are valid" + end end