##// END OF EJS Templates
Makes enumerations available through the REST API....
Jean-Philippe Lang -
r10453:d62b90db7327
parent child
Show More
@@ -0,0 +1,9
1 api.array @klass.name.underscore.pluralize do
2 @enumerations.each do |enumeration|
3 api.__send__ @klass.name.underscore do
4 api.id enumeration.id
5 api.name enumeration.name
6 api.is_default enumeration.is_default
7 end
8 end
9 end
@@ -0,0 +1,44
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 require File.expand_path('../../../test_helper', __FILE__)
19
20 class ApiTest::EnumerationsTest < ActionController::IntegrationTest
21 fixtures :enumerations
22
23 def setup
24 Setting.rest_api_enabled = '1'
25 end
26
27 context "/enumerations/issue_priorities" do
28 context "GET" do
29
30 should "return priorities" do
31 get '/enumerations/issue_priorities.xml'
32
33 assert_response :success
34 assert_equal 'application/xml', response.content_type
35 assert_select 'issue_priorities[type=array]' do
36 assert_select 'issue_priority' do
37 assert_select 'id', :text => '6'
38 assert_select 'name', :text => 'High'
39 end
40 end
41 end
42 end
43 end
44 end
@@ -1,85 +1,98
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class EnumerationsController < ApplicationController
19 19 layout 'admin'
20 20
21 before_filter :require_admin
21 before_filter :require_admin, :except => :index
22 before_filter :require_admin_or_api_request, :only => :index
22 23 before_filter :build_new_enumeration, :only => [:new, :create]
23 24 before_filter :find_enumeration, :only => [:edit, :update, :destroy]
25 accept_api_auth :index
24 26
25 27 helper :custom_fields
26 28
27 29 def index
30 respond_to do |format|
31 format.html
32 format.api {
33 @klass = Enumeration.get_subclass(params[:type])
34 if @klass
35 @enumerations = @klass.shared.sorted.all
36 else
37 render_404
38 end
39 }
40 end
28 41 end
29 42
30 43 def new
31 44 end
32 45
33 46 def create
34 47 if request.post? && @enumeration.save
35 48 flash[:notice] = l(:notice_successful_create)
36 redirect_to :action => 'index', :type => @enumeration.type
49 redirect_to :action => 'index'
37 50 else
38 51 render :action => 'new'
39 52 end
40 53 end
41 54
42 55 def edit
43 56 end
44 57
45 58 def update
46 59 if request.put? && @enumeration.update_attributes(params[:enumeration])
47 60 flash[:notice] = l(:notice_successful_update)
48 redirect_to :action => 'index', :type => @enumeration.type
61 redirect_to :action => 'index'
49 62 else
50 63 render :action => 'edit'
51 64 end
52 65 end
53 66
54 67 def destroy
55 68 if !@enumeration.in_use?
56 69 # No associated objects
57 70 @enumeration.destroy
58 71 redirect_to :action => 'index'
59 72 return
60 73 elsif params[:reassign_to_id]
61 74 if reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id])
62 75 @enumeration.destroy(reassign_to)
63 76 redirect_to :action => 'index'
64 77 return
65 78 end
66 79 end
67 80 @enumerations = @enumeration.class.all - [@enumeration]
68 81 end
69 82
70 83 private
71 84
72 85 def build_new_enumeration
73 86 class_name = params[:enumeration] && params[:enumeration][:type] || params[:type]
74 87 @enumeration = Enumeration.new_subclass_instance(class_name, params[:enumeration])
75 88 if @enumeration.nil?
76 89 render_404
77 90 end
78 91 end
79 92
80 93 def find_enumeration
81 94 @enumeration = Enumeration.find(params[:id])
82 95 rescue ActiveRecord::RecordNotFound
83 96 render_404
84 97 end
85 98 end
@@ -1,140 +1,141
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Enumeration < ActiveRecord::Base
19 19 include Redmine::SubclassFactory
20 20
21 21 default_scope :order => "#{Enumeration.table_name}.position ASC"
22 22
23 23 belongs_to :project
24 24
25 25 acts_as_list :scope => 'type = \'#{type}\''
26 26 acts_as_customizable
27 27 acts_as_tree :order => 'position ASC'
28 28
29 29 before_destroy :check_integrity
30 30 before_save :check_default
31 31
32 32 attr_protected :type
33 33
34 34 validates_presence_of :name
35 35 validates_uniqueness_of :name, :scope => [:type, :project_id]
36 36 validates_length_of :name, :maximum => 30
37 37
38 38 scope :shared, where(:project_id => nil)
39 scope :sorted, order("#{table_name}.position ASC")
39 40 scope :active, where(:active => true)
40 41 scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
41 42
42 43 def self.default
43 44 # Creates a fake default scope so Enumeration.default will check
44 45 # it's type. STI subclasses will automatically add their own
45 46 # types to the finder.
46 47 if self.descends_from_active_record?
47 48 where(:is_default => true, :type => 'Enumeration').first
48 49 else
49 50 # STI classes are
50 51 where(:is_default => true).first
51 52 end
52 53 end
53 54
54 55 # Overloaded on concrete classes
55 56 def option_name
56 57 nil
57 58 end
58 59
59 60 def check_default
60 61 if is_default? && is_default_changed?
61 62 Enumeration.update_all({:is_default => false}, {:type => type})
62 63 end
63 64 end
64 65
65 66 # Overloaded on concrete classes
66 67 def objects_count
67 68 0
68 69 end
69 70
70 71 def in_use?
71 72 self.objects_count != 0
72 73 end
73 74
74 75 # Is this enumeration overiding a system level enumeration?
75 76 def is_override?
76 77 !self.parent.nil?
77 78 end
78 79
79 80 alias :destroy_without_reassign :destroy
80 81
81 82 # Destroy the enumeration
82 83 # If a enumeration is specified, objects are reassigned
83 84 def destroy(reassign_to = nil)
84 85 if reassign_to && reassign_to.is_a?(Enumeration)
85 86 self.transfer_relations(reassign_to)
86 87 end
87 88 destroy_without_reassign
88 89 end
89 90
90 91 def <=>(enumeration)
91 92 position <=> enumeration.position
92 93 end
93 94
94 95 def to_s; name end
95 96
96 97 # Returns the Subclasses of Enumeration. Each Subclass needs to be
97 98 # required in development mode.
98 99 #
99 100 # Note: subclasses is protected in ActiveRecord
100 101 def self.get_subclasses
101 102 subclasses
102 103 end
103 104
104 105 # Does the +new+ Hash override the previous Enumeration?
105 106 def self.overridding_change?(new, previous)
106 107 if (same_active_state?(new['active'], previous.active)) && same_custom_values?(new,previous)
107 108 return false
108 109 else
109 110 return true
110 111 end
111 112 end
112 113
113 114 # Does the +new+ Hash have the same custom values as the previous Enumeration?
114 115 def self.same_custom_values?(new, previous)
115 116 previous.custom_field_values.each do |custom_value|
116 117 if custom_value.value != new["custom_field_values"][custom_value.custom_field_id.to_s]
117 118 return false
118 119 end
119 120 end
120 121
121 122 return true
122 123 end
123 124
124 125 # Are the new and previous fields equal?
125 126 def self.same_active_state?(new, previous)
126 127 new = (new == "1" ? true : false)
127 128 return new == previous
128 129 end
129 130
130 131 private
131 132 def check_integrity
132 133 raise "Can't delete enumeration" if self.in_use?
133 134 end
134 135
135 136 end
136 137
137 138 # Force load the subclasses in development mode
138 139 require_dependency 'time_entry_activity'
139 140 require_dependency 'document_category'
140 141 require_dependency 'issue_priority'
@@ -1,344 +1,345
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 RedmineApp::Application.routes.draw do
19 19 root :to => 'welcome#index', :as => 'home'
20 20
21 21 match 'login', :to => 'account#login', :as => 'signin'
22 22 match 'logout', :to => 'account#logout', :as => 'signout'
23 23 match 'account/register', :to => 'account#register', :via => [:get, :post], :as => 'register'
24 24 match 'account/lost_password', :to => 'account#lost_password', :via => [:get, :post], :as => 'lost_password'
25 25 match 'account/activate', :to => 'account#activate', :via => :get
26 26
27 27 match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news'
28 28 match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue'
29 29 match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue'
30 30 match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue'
31 31
32 32 match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post
33 33 match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post]
34 34
35 35 match 'boards/:board_id/topics/new', :to => 'messages#new', :via => [:get, :post]
36 36 get 'boards/:board_id/topics/:id', :to => 'messages#show', :as => 'board_message'
37 37 match 'boards/:board_id/topics/quote/:id', :to => 'messages#quote', :via => [:get, :post]
38 38 get 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
39 39
40 40 post 'boards/:board_id/topics/preview', :to => 'messages#preview'
41 41 post 'boards/:board_id/topics/:id/replies', :to => 'messages#reply'
42 42 post 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
43 43 post 'boards/:board_id/topics/:id/destroy', :to => 'messages#destroy'
44 44
45 45 # Misc issue routes. TODO: move into resources
46 46 match '/issues/auto_complete', :to => 'auto_completes#issues', :via => :get, :as => 'auto_complete_issues'
47 47 match '/issues/context_menu', :to => 'context_menus#issues', :as => 'issues_context_menu'
48 48 match '/issues/changes', :to => 'journals#index', :as => 'issue_changes'
49 49 match '/issues/:id/quoted', :to => 'journals#new', :id => /\d+/, :via => :post, :as => 'quoted_issue'
50 50
51 51 match '/journals/diff/:id', :to => 'journals#diff', :id => /\d+/, :via => :get
52 52 match '/journals/edit/:id', :to => 'journals#edit', :id => /\d+/, :via => [:get, :post]
53 53
54 54 match '/projects/:project_id/issues/gantt', :to => 'gantts#show'
55 55 match '/issues/gantt', :to => 'gantts#show'
56 56
57 57 match '/projects/:project_id/issues/calendar', :to => 'calendars#show'
58 58 match '/issues/calendar', :to => 'calendars#show'
59 59
60 60 match 'projects/:id/issues/report', :to => 'reports#issue_report', :via => :get
61 61 match 'projects/:id/issues/report/:detail', :to => 'reports#issue_report_details', :via => :get
62 62
63 63 match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
64 64 match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
65 65 match 'my/page', :controller => 'my', :action => 'page', :via => :get
66 66 match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page
67 67 match 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key', :via => :post
68 68 match 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key', :via => :post
69 69 match 'my/password', :controller => 'my', :action => 'password', :via => [:get, :post]
70 70 match 'my/page_layout', :controller => 'my', :action => 'page_layout', :via => :get
71 71 match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post
72 72 match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post
73 73 match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post
74 74
75 75 resources :users
76 76 match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => :put, :as => 'user_membership'
77 77 match 'users/:id/memberships/:membership_id', :to => 'users#destroy_membership', :via => :delete
78 78 match 'users/:id/memberships', :to => 'users#edit_membership', :via => :post, :as => 'user_memberships'
79 79
80 80 match 'watchers/new', :controller=> 'watchers', :action => 'new', :via => :get
81 81 match 'watchers', :controller=> 'watchers', :action => 'create', :via => :post
82 82 match 'watchers/append', :controller=> 'watchers', :action => 'append', :via => :post
83 83 match 'watchers/destroy', :controller=> 'watchers', :action => 'destroy', :via => :post
84 84 match 'watchers/watch', :controller=> 'watchers', :action => 'watch', :via => :post
85 85 match 'watchers/unwatch', :controller=> 'watchers', :action => 'unwatch', :via => :post
86 86 match 'watchers/autocomplete_for_user', :controller=> 'watchers', :action => 'autocomplete_for_user', :via => :get
87 87
88 88 match 'projects/:id/settings/:tab', :to => "projects#settings"
89 89
90 90 resources :projects do
91 91 member do
92 92 get 'settings'
93 93 post 'modules'
94 94 post 'archive'
95 95 post 'unarchive'
96 96 post 'close'
97 97 post 'reopen'
98 98 match 'copy', :via => [:get, :post]
99 99 end
100 100
101 resources :memberships, :shallow => true, :controller => 'members', :only => [:index, :show, :create, :update, :destroy] do
101 resources :memberships, :shallow => true, :controller => 'members', :only => [:index, :show, :new, :create, :update, :destroy] do
102 102 collection do
103 103 get 'autocomplete'
104 104 end
105 105 end
106 106
107 107 resource :enumerations, :controller => 'project_enumerations', :only => [:update, :destroy]
108 108
109 109 match 'issues/:copy_from/copy', :to => 'issues#new'
110 110 resources :issues, :only => [:index, :new, :create] do
111 111 resources :time_entries, :controller => 'timelog' do
112 112 collection do
113 113 get 'report'
114 114 end
115 115 end
116 116 end
117 117 # issue form update
118 118 match 'issues/new', :controller => 'issues', :action => 'new', :via => [:put, :post], :as => 'issue_form'
119 119
120 120 resources :files, :only => [:index, :new, :create]
121 121
122 122 resources :versions, :except => [:index, :show, :edit, :update, :destroy] do
123 123 collection do
124 124 put 'close_completed'
125 125 end
126 126 end
127 127 match 'versions.:format', :to => 'versions#index'
128 128 match 'roadmap', :to => 'versions#index', :format => false
129 129 match 'versions', :to => 'versions#index'
130 130
131 131 resources :news, :except => [:show, :edit, :update, :destroy]
132 132 resources :time_entries, :controller => 'timelog' do
133 133 get 'report', :on => :collection
134 134 end
135 135 resources :queries, :only => [:new, :create]
136 136 resources :issue_categories, :shallow => true
137 137 resources :documents, :except => [:show, :edit, :update, :destroy]
138 138 resources :boards
139 139 resources :repositories, :shallow => true, :except => [:index, :show] do
140 140 member do
141 141 match 'committers', :via => [:get, :post]
142 142 end
143 143 end
144 144
145 145 match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
146 146 match 'wiki/:id/diff/:version/vs/:version_from', :controller => 'wiki', :action => 'diff'
147 147 match 'wiki/:id/diff/:version', :controller => 'wiki', :action => 'diff'
148 148 resources :wiki, :except => [:index, :new, :create] do
149 149 member do
150 150 get 'rename'
151 151 post 'rename'
152 152 get 'history'
153 153 get 'diff'
154 154 match 'preview', :via => [:post, :put]
155 155 post 'protect'
156 156 post 'add_attachment'
157 157 end
158 158 collection do
159 159 get 'export'
160 160 get 'date_index'
161 161 end
162 162 end
163 163 match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
164 164 match 'wiki/:id/annotate/:version', :controller => 'wiki', :action => 'annotate'
165 165 end
166 166
167 167 resources :issues do
168 168 collection do
169 169 match 'bulk_edit', :via => [:get, :post]
170 170 post 'bulk_update'
171 171 end
172 172 resources :time_entries, :controller => 'timelog' do
173 173 collection do
174 174 get 'report'
175 175 end
176 176 end
177 177 resources :relations, :shallow => true, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy]
178 178 end
179 179 match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete
180 180
181 181 resources :queries, :except => [:show]
182 182
183 183 resources :news, :only => [:index, :show, :edit, :update, :destroy]
184 184 match '/news/:id/comments', :to => 'comments#create', :via => :post
185 185 match '/news/:id/comments/:comment_id', :to => 'comments#destroy', :via => :delete
186 186
187 187 resources :versions, :only => [:show, :edit, :update, :destroy] do
188 188 post 'status_by', :on => :member
189 189 end
190 190
191 191 resources :documents, :only => [:show, :edit, :update, :destroy] do
192 192 post 'add_attachment', :on => :member
193 193 end
194 194
195 195 match '/time_entries/context_menu', :to => 'context_menus#time_entries', :as => :time_entries_context_menu
196 196
197 197 resources :time_entries, :controller => 'timelog', :except => :destroy do
198 198 collection do
199 199 get 'report'
200 200 get 'bulk_edit'
201 201 post 'bulk_update'
202 202 end
203 203 end
204 204 match '/time_entries/:id', :to => 'timelog#destroy', :via => :delete, :id => /\d+/
205 205 # TODO: delete /time_entries for bulk deletion
206 206 match '/time_entries/destroy', :to => 'timelog#destroy', :via => :delete
207 207
208 208 # TODO: port to be part of the resources route(s)
209 209 match 'projects/:id/settings/:tab', :to => 'projects#settings', :via => :get
210 210
211 211 get 'projects/:id/activity', :to => 'activities#index'
212 212 get 'projects/:id/activity.:format', :to => 'activities#index'
213 213 get 'activity', :to => 'activities#index'
214 214
215 215 # repositories routes
216 216 get 'projects/:id/repository/:repository_id/statistics', :to => 'repositories#stats'
217 217 get 'projects/:id/repository/:repository_id/graph', :to => 'repositories#graph'
218 218
219 219 get 'projects/:id/repository/:repository_id/changes(/*path(.:ext))',
220 220 :to => 'repositories#changes'
221 221
222 222 get 'projects/:id/repository/:repository_id/revisions/:rev', :to => 'repositories#revision'
223 223 get 'projects/:id/repository/:repository_id/revision', :to => 'repositories#revision'
224 224 post 'projects/:id/repository/:repository_id/revisions/:rev/issues', :to => 'repositories#add_related_issue'
225 225 delete 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
226 226 get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions'
227 227 get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))',
228 228 :controller => 'repositories',
229 229 :format => false,
230 230 :constraints => {
231 231 :action => /(browse|show|entry|raw|annotate|diff)/,
232 232 :rev => /[a-z0-9\.\-_]+/
233 233 }
234 234
235 235 get 'projects/:id/repository/statistics', :to => 'repositories#stats'
236 236 get 'projects/:id/repository/graph', :to => 'repositories#graph'
237 237
238 238 get 'projects/:id/repository/changes(/*path(.:ext))',
239 239 :to => 'repositories#changes'
240 240
241 241 get 'projects/:id/repository/revisions', :to => 'repositories#revisions'
242 242 get 'projects/:id/repository/revisions/:rev', :to => 'repositories#revision'
243 243 get 'projects/:id/repository/revision', :to => 'repositories#revision'
244 244 post 'projects/:id/repository/revisions/:rev/issues', :to => 'repositories#add_related_issue'
245 245 delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
246 246 get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))',
247 247 :controller => 'repositories',
248 248 :format => false,
249 249 :constraints => {
250 250 :action => /(browse|show|entry|raw|annotate|diff)/,
251 251 :rev => /[a-z0-9\.\-_]+/
252 252 }
253 253 get 'projects/:id/repository/:repository_id/:action(/*path(.:ext))',
254 254 :controller => 'repositories',
255 255 :action => /(browse|show|entry|raw|changes|annotate|diff)/
256 256 get 'projects/:id/repository/:action(/*path(.:ext))',
257 257 :controller => 'repositories',
258 258 :action => /(browse|show|entry|raw|changes|annotate|diff)/
259 259
260 260 get 'projects/:id/repository/:repository_id', :to => 'repositories#show', :path => nil
261 261 get 'projects/:id/repository', :to => 'repositories#show', :path => nil
262 262
263 263 # additional routes for having the file name at the end of url
264 264 match 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/, :via => :get
265 265 match 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/, :via => :get
266 266 match 'attachments/download/:id', :controller => 'attachments', :action => 'download', :id => /\d+/, :via => :get
267 267 match 'attachments/thumbnail/:id(/:size)', :controller => 'attachments', :action => 'thumbnail', :id => /\d+/, :via => :get, :size => /\d+/
268 268 resources :attachments, :only => [:show, :destroy]
269 269
270 270 resources :groups do
271 271 member do
272 272 get 'autocomplete_for_user'
273 273 end
274 274 end
275 275
276 276 match 'groups/:id/users', :controller => 'groups', :action => 'add_users', :id => /\d+/, :via => :post, :as => 'group_users'
277 277 match 'groups/:id/users/:user_id', :controller => 'groups', :action => 'remove_user', :id => /\d+/, :via => :delete, :as => 'group_user'
278 278 match 'groups/destroy_membership/:id', :controller => 'groups', :action => 'destroy_membership', :id => /\d+/, :via => :post
279 279 match 'groups/edit_membership/:id', :controller => 'groups', :action => 'edit_membership', :id => /\d+/, :via => :post
280 280
281 281 resources :trackers, :except => :show do
282 282 collection do
283 283 match 'fields', :via => [:get, :post]
284 284 end
285 285 end
286 286 resources :issue_statuses, :except => :show do
287 287 collection do
288 288 post 'update_issue_done_ratio'
289 289 end
290 290 end
291 291 resources :custom_fields, :except => :show
292 292 resources :roles do
293 293 collection do
294 294 match 'permissions', :via => [:get, :post]
295 295 end
296 296 end
297 297 resources :enumerations, :except => :show
298 match 'enumerations/:type', :to => 'enumerations#index', :via => :get
298 299
299 300 get 'projects/:id/search', :controller => 'search', :action => 'index'
300 301 get 'search', :controller => 'search', :action => 'index'
301 302
302 303 match 'mail_handler', :controller => 'mail_handler', :action => 'index', :via => :post
303 304
304 305 match 'admin', :controller => 'admin', :action => 'index', :via => :get
305 306 match 'admin/projects', :controller => 'admin', :action => 'projects', :via => :get
306 307 match 'admin/plugins', :controller => 'admin', :action => 'plugins', :via => :get
307 308 match 'admin/info', :controller => 'admin', :action => 'info', :via => :get
308 309 match 'admin/test_email', :controller => 'admin', :action => 'test_email', :via => :get
309 310 match 'admin/default_configuration', :controller => 'admin', :action => 'default_configuration', :via => :post
310 311
311 312 resources :auth_sources do
312 313 member do
313 314 get 'test_connection'
314 315 end
315 316 end
316 317
317 318 match 'workflows', :controller => 'workflows', :action => 'index', :via => :get
318 319 match 'workflows/edit', :controller => 'workflows', :action => 'edit', :via => [:get, :post]
319 320 match 'workflows/permissions', :controller => 'workflows', :action => 'permissions', :via => [:get, :post]
320 321 match 'workflows/copy', :controller => 'workflows', :action => 'copy', :via => [:get, :post]
321 322 match 'settings', :controller => 'settings', :action => 'index', :via => :get
322 323 match 'settings/edit', :controller => 'settings', :action => 'edit', :via => [:get, :post]
323 324 match 'settings/plugin/:id', :controller => 'settings', :action => 'plugin', :via => [:get, :post]
324 325
325 326 match 'sys/projects', :to => 'sys#projects', :via => :get
326 327 match 'sys/projects/:id/repository', :to => 'sys#create_project_repository', :via => :post
327 328 match 'sys/fetch_changesets', :to => 'sys#fetch_changesets', :via => :get
328 329
329 330 match 'uploads', :to => 'attachments#upload', :via => :post
330 331
331 332 get 'robots.txt', :to => 'welcome#robots'
332 333
333 334 Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir|
334 335 file = File.join(plugin_dir, "config/routes.rb")
335 336 if File.exists?(file)
336 337 begin
337 338 instance_eval File.read(file)
338 339 rescue Exception => e
339 340 puts "An error occurred while loading the routes definition of #{File.basename(plugin_dir)} plugin (#{file}): #{e.message}."
340 341 exit 1
341 342 end
342 343 end
343 344 end
344 345 end
@@ -1,42 +1,47
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 module Redmine
19 19 module SubclassFactory
20 20 def self.included(base)
21 21 base.extend ClassMethods
22 22 end
23 23
24 24 module ClassMethods
25 # Returns an instance of the given subclass name
26 def new_subclass_instance(class_name, *args)
25 def get_subclass(class_name)
27 26 klass = nil
28 27 begin
29 28 klass = class_name.to_s.classify.constantize
30 29 rescue
31 30 # invalid class name
32 31 end
33 32 unless subclasses.include? klass
34 33 klass = nil
35 34 end
35 klass
36 end
37
38 # Returns an instance of the given subclass name
39 def new_subclass_instance(class_name, *args)
40 klass = get_subclass(class_name)
36 41 if klass
37 42 klass.new(*args)
38 43 end
39 44 end
40 45 end
41 46 end
42 47 end
@@ -1,123 +1,129
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class EnumerationsControllerTest < ActionController::TestCase
21 21 fixtures :enumerations, :issues, :users
22 22
23 23 def setup
24 24 @request.session[:user_id] = 1 # admin
25 25 end
26 26
27 27 def test_index
28 28 get :index
29 29 assert_response :success
30 30 assert_template 'index'
31 31 end
32 32
33 def test_index_should_require_admin
34 @request.session[:user_id] = nil
35 get :index
36 assert_response 302
37 end
38
33 39 def test_new
34 40 get :new, :type => 'IssuePriority'
35 41 assert_response :success
36 42 assert_template 'new'
37 43 assert_kind_of IssuePriority, assigns(:enumeration)
38 44 assert_tag 'input', :attributes => {:name => 'enumeration[type]', :value => 'IssuePriority'}
39 45 assert_tag 'input', :attributes => {:name => 'enumeration[name]'}
40 46 end
41 47
42 48 def test_new_with_invalid_type_should_respond_with_404
43 49 get :new, :type => 'UnknownType'
44 50 assert_response 404
45 51 end
46 52
47 53 def test_create
48 54 assert_difference 'IssuePriority.count' do
49 55 post :create, :enumeration => {:type => 'IssuePriority', :name => 'Lowest'}
50 56 end
51 assert_redirected_to '/enumerations?type=IssuePriority'
57 assert_redirected_to '/enumerations'
52 58 e = IssuePriority.find_by_name('Lowest')
53 59 assert_not_nil e
54 60 end
55 61
56 62 def test_create_with_failure
57 63 assert_no_difference 'IssuePriority.count' do
58 64 post :create, :enumeration => {:type => 'IssuePriority', :name => ''}
59 65 end
60 66 assert_response :success
61 67 assert_template 'new'
62 68 end
63 69
64 70 def test_edit
65 71 get :edit, :id => 6
66 72 assert_response :success
67 73 assert_template 'edit'
68 74 assert_tag 'input', :attributes => {:name => 'enumeration[name]', :value => 'High'}
69 75 end
70 76
71 77 def test_edit_invalid_should_respond_with_404
72 78 get :edit, :id => 999
73 79 assert_response 404
74 80 end
75 81
76 82 def test_update
77 83 assert_no_difference 'IssuePriority.count' do
78 84 put :update, :id => 6, :enumeration => {:type => 'IssuePriority', :name => 'New name'}
79 85 end
80 assert_redirected_to '/enumerations?type=IssuePriority'
86 assert_redirected_to '/enumerations'
81 87 e = IssuePriority.find(6)
82 88 assert_equal 'New name', e.name
83 89 end
84 90
85 91 def test_update_with_failure
86 92 assert_no_difference 'IssuePriority.count' do
87 93 put :update, :id => 6, :enumeration => {:type => 'IssuePriority', :name => ''}
88 94 end
89 95 assert_response :success
90 96 assert_template 'edit'
91 97 end
92 98
93 99 def test_destroy_enumeration_not_in_use
94 100 assert_difference 'IssuePriority.count', -1 do
95 101 delete :destroy, :id => 7
96 102 end
97 103 assert_redirected_to :controller => 'enumerations', :action => 'index'
98 104 assert_nil Enumeration.find_by_id(7)
99 105 end
100 106
101 107 def test_destroy_enumeration_in_use
102 108 assert_no_difference 'IssuePriority.count' do
103 109 delete :destroy, :id => 4
104 110 end
105 111 assert_response :success
106 112 assert_template 'destroy'
107 113 assert_not_nil Enumeration.find_by_id(4)
108 114 assert_select 'select[name=reassign_to_id]' do
109 115 assert_select 'option[value=6]', :text => 'High'
110 116 end
111 117 end
112 118
113 119 def test_destroy_enumeration_in_use_with_reassignment
114 120 issue = Issue.find(:first, :conditions => {:priority_id => 4})
115 121 assert_difference 'IssuePriority.count', -1 do
116 122 delete :destroy, :id => 4, :reassign_to_id => 6
117 123 end
118 124 assert_redirected_to :controller => 'enumerations', :action => 'index'
119 125 assert_nil Enumeration.find_by_id(4)
120 126 # check that the issue was reassign
121 127 assert_equal 6, issue.reload.priority_id
122 128 end
123 129 end
@@ -1,47 +1,51
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../../test_helper', __FILE__)
19 19
20 20 class RoutingEnumerationsTest < ActionController::IntegrationTest
21 21 def test_enumerations
22 22 assert_routing(
23 23 { :method => 'get', :path => "/enumerations" },
24 24 { :controller => 'enumerations', :action => 'index' }
25 25 )
26 26 assert_routing(
27 27 { :method => 'get', :path => "/enumerations/new" },
28 28 { :controller => 'enumerations', :action => 'new' }
29 29 )
30 30 assert_routing(
31 31 { :method => 'post', :path => "/enumerations" },
32 32 { :controller => 'enumerations', :action => 'create' }
33 33 )
34 34 assert_routing(
35 35 { :method => 'get', :path => "/enumerations/2/edit" },
36 36 { :controller => 'enumerations', :action => 'edit', :id => '2' }
37 37 )
38 38 assert_routing(
39 39 { :method => 'put', :path => "/enumerations/2" },
40 40 { :controller => 'enumerations', :action => 'update', :id => '2' }
41 41 )
42 42 assert_routing(
43 43 { :method => 'delete', :path => "/enumerations/2" },
44 44 { :controller => 'enumerations', :action => 'destroy', :id => '2' }
45 45 )
46 assert_routing(
47 { :method => 'get', :path => "/enumerations/issue_priorities.xml" },
48 { :controller => 'enumerations', :action => 'index', :type => 'issue_priorities', :format => 'xml' }
49 )
46 50 end
47 51 end
General Comments 0
You need to be logged in to leave comments. Login now