diff --git a/app/controllers/enumerations_controller.rb b/app/controllers/enumerations_controller.rb index 7a7f1685..788fa11b 100644 --- a/app/controllers/enumerations_controller.rb +++ b/app/controllers/enumerations_controller.rb @@ -75,11 +75,20 @@ class EnumerationsController < ApplicationController end def destroy - Enumeration.find(params[:id]).destroy - flash[:notice] = l(:notice_successful_delete) - redirect_to :action => 'list' - rescue - flash[:error] = "Unable to delete enumeration" - redirect_to :action => 'list' + @enumeration = Enumeration.find(params[:id]) + if !@enumeration.in_use? + # No associated objects + @enumeration.destroy + redirect_to :action => 'index' + elsif params[:reassign_to_id] + if reassign_to = Enumeration.find_by_opt_and_id(@enumeration.opt, params[:reassign_to_id]) + @enumeration.destroy(reassign_to) + redirect_to :action => 'index' + end + end + @enumerations = Enumeration.get_values(@enumeration.opt) - [@enumeration] + #rescue + # flash[:error] = 'Unable to delete enumeration' + # redirect_to :action => 'index' end end diff --git a/app/models/enumeration.rb b/app/models/enumeration.rb index e8676872..d32a0c04 100644 --- a/app/models/enumeration.rb +++ b/app/models/enumeration.rb @@ -24,10 +24,11 @@ class Enumeration < ActiveRecord::Base validates_uniqueness_of :name, :scope => [:opt] validates_length_of :name, :maximum => 30 + # Single table inheritance would be an option OPTIONS = { - "IPRI" => :enumeration_issue_priorities, - "DCAT" => :enumeration_doc_categories, - "ACTI" => :enumeration_activities + "IPRI" => {:label => :enumeration_issue_priorities, :model => Issue, :foreign_key => :priority_id}, + "DCAT" => {:label => :enumeration_doc_categories, :model => Document, :foreign_key => :category_id}, + "ACTI" => {:label => :enumeration_activities, :model => TimeEntry, :foreign_key => :activity_id} }.freeze def self.get_values(option) @@ -39,13 +40,32 @@ class Enumeration < ActiveRecord::Base end def option_name - OPTIONS[self.opt] + OPTIONS[self.opt][:label] end def before_save Enumeration.update_all("is_default = #{connection.quoted_false}", {:opt => opt}) if is_default? end + def objects_count + OPTIONS[self.opt][:model].count(:conditions => "#{OPTIONS[self.opt][:foreign_key]} = #{id}") + end + + def in_use? + self.objects_count != 0 + end + + alias :destroy_without_reassign :destroy + + # Destroy the enumeration + # If a enumeration is specified, objects are reassigned + def destroy(reassign_to = nil) + if reassign_to && reassign_to.is_a?(Enumeration) + OPTIONS[self.opt][:model].update_all("#{OPTIONS[self.opt][:foreign_key]} = #{reassign_to.id}", "#{OPTIONS[self.opt][:foreign_key]} = #{id}") + end + destroy_without_reassign + end + def <=>(enumeration) position <=> enumeration.position end @@ -54,13 +74,6 @@ class Enumeration < ActiveRecord::Base private def check_integrity - case self.opt - when "IPRI" - raise "Can't delete enumeration" if Issue.find(:first, :conditions => ["priority_id=?", self.id]) - when "DCAT" - raise "Can't delete enumeration" if Document.find(:first, :conditions => ["category_id=?", self.id]) - when "ACTI" - raise "Can't delete enumeration" if TimeEntry.find(:first, :conditions => ["activity_id=?", self.id]) - end + raise "Can't delete enumeration" if self.in_use? end end diff --git a/app/views/enumerations/destroy.rhtml b/app/views/enumerations/destroy.rhtml new file mode 100644 index 00000000..657df832 --- /dev/null +++ b/app/views/enumerations/destroy.rhtml @@ -0,0 +1,12 @@ +

<%= l(@enumeration.option_name) %>: <%=h @enumeration %>

+ +<% form_tag({}) do %> +
+

<%= l(:text_enumeration_destroy_question, @enumeration.objects_count) %>

+

<%= l(:text_enumeration_category_reassign_to) %> +<%= select_tag 'reassign_to_id', ("" + options_from_collection_for_select(@enumerations, 'id', 'name')) %>

+
+ +<%= submit_tag l(:button_apply) %> +<%= link_to l(:button_cancel), :controller => 'enumerations', :action => 'index' %> +<% end %> diff --git a/app/views/enumerations/list.rhtml b/app/views/enumerations/list.rhtml index 1967e5cf..7f3886b4 100644 --- a/app/views/enumerations/list.rhtml +++ b/app/views/enumerations/list.rhtml @@ -1,7 +1,7 @@

<%=l(:label_enumerations)%>

-<% Enumeration::OPTIONS.each do |option, name| %> -

<%= l(name) %>

+<% Enumeration::OPTIONS.each do |option, params| %> +

<%= l(params[:label]) %>

<% enumerations = Enumeration.get_values(option) %> <% if enumerations.any? %> @@ -16,6 +16,9 @@ <%= link_to image_tag('1downarrow.png', :alt => l(:label_sort_lower)), {:action => 'move', :id => enumeration, :position => 'lower'}, :method => :post, :title => l(:label_sort_lower) %> <%= link_to image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), {:action => 'move', :id => enumeration, :position => 'lowest'}, :method => :post, :title => l(:label_sort_lowest) %> + + <%= link_to l(:button_delete), { :action => 'destroy', :id => enumeration }, :method => :post, :confirm => l(:text_are_you_sure), :class => "icon icon-del" %> + <% end %> diff --git a/lang/bg.yml b/lang/bg.yml index 5f354868..48226c79 100644 --- a/lang/bg.yml +++ b/lang/bg.yml @@ -624,3 +624,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/cs.yml b/lang/cs.yml index 26e0f513..de460ba3 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -629,3 +629,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/da.yml b/lang/da.yml index b2f18db4..6919cdfc 100644 --- a/lang/da.yml +++ b/lang/da.yml @@ -626,3 +626,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/de.yml b/lang/de.yml index 1e4040f3..290acd91 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -625,3 +625,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/en.yml b/lang/en.yml index b7f217e6..ffbd1062 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -599,6 +599,8 @@ text_destroy_time_entries: Delete reported hours text_assign_time_entries_to_project: Assign reported hours to the project text_reassign_time_entries: 'Reassign reported hours to this issue:' text_user_wrote: '%s wrote:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' +text_enumeration_category_reassign_to: 'Reassign them to this value:' default_role_manager: Manager default_role_developper: Developer diff --git a/lang/es.yml b/lang/es.yml index c0ecb997..b027f48e 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -627,3 +627,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/fi.yml b/lang/fi.yml index 6ac4aea7..e1d188dc 100644 --- a/lang/fi.yml +++ b/lang/fi.yml @@ -624,3 +624,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/fr.yml b/lang/fr.yml index 4db2f8f3..eaae5176 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -599,6 +599,8 @@ text_destroy_time_entries: Supprimer les heures text_assign_time_entries_to_project: Reporter les heures sur le projet text_reassign_time_entries: 'Reporter les heures sur cette demande:' text_user_wrote: '%s a écrit:' +text_enumeration_destroy_question: 'Cette valeur est affectée à %d objets.' +text_enumeration_category_reassign_to: 'Réaffecter les objets à cette valeur:' default_role_manager: Manager default_role_developper: Développeur diff --git a/lang/he.yml b/lang/he.yml index e23698d3..5f14ee16 100644 --- a/lang/he.yml +++ b/lang/he.yml @@ -624,3 +624,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/hu.yml b/lang/hu.yml index 1df06194..c46d0e26 100644 --- a/lang/hu.yml +++ b/lang/hu.yml @@ -625,3 +625,5 @@ mail_subject_reminder: "%d feladat határidős az elkövetkező napokban" text_user_wrote: '%s írta:' label_duplicated_by: duplikálta setting_enabled_scm: Forráskódkezelő (SCM) engedélyezése +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/it.yml b/lang/it.yml index 5ab9ad31..8aec9ef0 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -624,3 +624,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/ja.yml b/lang/ja.yml index c693d68e..c48579dd 100644 --- a/lang/ja.yml +++ b/lang/ja.yml @@ -625,3 +625,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/ko.yml b/lang/ko.yml index af1c768a..f2339556 100644 --- a/lang/ko.yml +++ b/lang/ko.yml @@ -624,3 +624,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/lt.yml b/lang/lt.yml index ff8f6b69..61533b3a 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -626,3 +626,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/nl.yml b/lang/nl.yml index 9ee91384..109d444f 100644 --- a/lang/nl.yml +++ b/lang/nl.yml @@ -625,3 +625,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/no.yml b/lang/no.yml index aa9d0396..4e47c75a 100644 --- a/lang/no.yml +++ b/lang/no.yml @@ -625,3 +625,5 @@ default_activity_development: Utvikling enumeration_issue_priorities: Sakssprioriteringer enumeration_doc_categories: Dokument-kategorier enumeration_activities: Aktiviteter (tidssporing) +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/pl.yml b/lang/pl.yml index 75e04ecd..97378b5b 100644 --- a/lang/pl.yml +++ b/lang/pl.yml @@ -624,3 +624,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/pt-br.yml b/lang/pt-br.yml index dabab5bf..67822499 100644 --- a/lang/pt-br.yml +++ b/lang/pt-br.yml @@ -624,3 +624,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/pt.yml b/lang/pt.yml index 2845f390..a91eea01 100644 --- a/lang/pt.yml +++ b/lang/pt.yml @@ -624,3 +624,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/ro.yml b/lang/ro.yml index dd51e59b..aafc6191 100644 --- a/lang/ro.yml +++ b/lang/ro.yml @@ -624,3 +624,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/ru.yml b/lang/ru.yml index c3ec9189..e0437778 100644 --- a/lang/ru.yml +++ b/lang/ru.yml @@ -628,3 +628,5 @@ mail_subject_reminder: "%d назначенных на вас задач в бл text_user_wrote: '%s написал:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/sr.yml b/lang/sr.yml index 92906760..ec01774b 100644 --- a/lang/sr.yml +++ b/lang/sr.yml @@ -625,3 +625,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/sv.yml b/lang/sv.yml index f08e45eb..e28943d9 100644 --- a/lang/sv.yml +++ b/lang/sv.yml @@ -625,3 +625,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/th.yml b/lang/th.yml index 85a1f8c0..6c84dba7 100644 --- a/lang/th.yml +++ b/lang/th.yml @@ -627,3 +627,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/uk.yml b/lang/uk.yml index ae8c5cbc..365ced15 100644 --- a/lang/uk.yml +++ b/lang/uk.yml @@ -626,3 +626,5 @@ mail_subject_reminder: "%d issue(s) due in the next days" text_user_wrote: '%s wrote:' label_duplicated_by: duplicated by setting_enabled_scm: Enabled SCM +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/zh-tw.yml b/lang/zh-tw.yml index 064004c3..c7b47354 100644 --- a/lang/zh-tw.yml +++ b/lang/zh-tw.yml @@ -625,3 +625,5 @@ default_activity_development: 開發 enumeration_issue_priorities: 項目優先權 enumeration_doc_categories: 文件分類 enumeration_activities: 活動 (時間追蹤) +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/lang/zh.yml b/lang/zh.yml index ac650c85..981e8102 100644 --- a/lang/zh.yml +++ b/lang/zh.yml @@ -625,3 +625,5 @@ default_activity_development: 开发 enumeration_issue_priorities: 问题优先级 enumeration_doc_categories: 文档类别 enumeration_activities: 活动(时间跟踪) +text_enumeration_category_reassign_to: 'Reassign them to this value:' +text_enumeration_destroy_question: '%d objects are assigned to this value.' diff --git a/test/functional/enumerations_controller.rb b/test/functional/enumerations_controller.rb new file mode 100644 index 00000000..36ff8672 --- /dev/null +++ b/test/functional/enumerations_controller.rb @@ -0,0 +1,61 @@ +# redMine - project management software +# Copyright (C) 2006-2008 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.dirname(__FILE__) + '/../test_helper' +require 'enumerations_controller' + +# Re-raise errors caught by the controller. +class EnumerationsController; def rescue_action(e) raise e end; end + +class EnumerationsControllerTest < Test::Unit::TestCase + fixtures :enumerations, :issues, :users + + def setup + @controller = EnumerationsController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @request.session[:user_id] = 1 # admin + end + + def test_index + get :index + assert_response :success + assert_template 'list' + end + + def test_destroy_enumeration_not_in_use + post :destroy, :id => 7 + assert_redirected_to :controller => 'enumerations', :action => 'index' + assert_nil Enumeration.find_by_id(7) + end + + def test_destroy_enumeration_in_use + post :destroy, :id => 4 + assert_response :success + assert_template 'destroy' + assert_not_nil Enumeration.find_by_id(4) + end + + def test_destroy_enumeration_in_use_with_reassignment + issue = Issue.find(:first, :conditions => {:priority_id => 4}) + post :destroy, :id => 4, :reassign_to_id => 6 + assert_redirected_to :controller => 'enumerations', :action => 'index' + assert_nil Enumeration.find_by_id(4) + # check that the issue was reassign + assert_equal 6, issue.reload.priority_id + end +end diff --git a/test/unit/enumeration_test.rb b/test/unit/enumeration_test.rb new file mode 100644 index 00000000..9b7bfd17 --- /dev/null +++ b/test/unit/enumeration_test.rb @@ -0,0 +1,45 @@ +# redMine - project management software +# Copyright (C) 2006-2008 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.dirname(__FILE__) + '/../test_helper' + +class EnumerationTest < Test::Unit::TestCase + fixtures :enumerations, :issues + + def setup + end + + def test_objects_count + # low priority + assert_equal 5, Enumeration.find(4).objects_count + # urgent + assert_equal 0, Enumeration.find(7).objects_count + end + + def test_in_use + # low priority + assert Enumeration.find(4).in_use? + # urgent + assert !Enumeration.find(7).in_use? + end + + def test_destroy_with_reassign + Enumeration.find(4).destroy(Enumeration.find(6)) + assert_nil Issue.find(:first, :conditions => {:priority_id => 4}) + assert_equal 5, Enumeration.find(6).objects_count + end +end