Project

General

Profile

« Previous | Next » 

Revision 7882

REST API for issue categories (#9553).

View differences:

trunk/app/controllers/issue_categories_controller.rb
18 18
class IssueCategoriesController < ApplicationController
19 19
  menu_item :settings
20 20
  model_object IssueCategory
21
  before_filter :find_model_object, :except => [:new, :create]
22
  before_filter :find_project_from_association, :except => [:new, :create]
23
  before_filter :find_project, :only => [:new, :create]
21
  before_filter :find_model_object, :except => [:index, :new, :create]
22
  before_filter :find_project_from_association, :except => [:index, :new, :create]
23
  before_filter :find_project, :only => [:index, :new, :create]
24 24
  before_filter :authorize
25
  accept_api_auth :index, :show, :create, :update, :destroy
26
  
27
  def index
28
    respond_to do |format|
29
      format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project }
30
      format.api { @categories = @project.issue_categories.all }
31
    end
32
  end
25 33

  
34
  def show
35
    respond_to do |format|
36
      format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project }
37
      format.api
38
    end
39
  end
40

  
26 41
  def new
27
    @category = @project.issue_categories.build(params[:category])
42
    @category = @project.issue_categories.build(params[:issue_category])
28 43
  end
29 44

  
30 45
  verify :method => :post, :only => :create
31 46
  def create
32
    @category = @project.issue_categories.build(params[:category])
47
    @category = @project.issue_categories.build(params[:issue_category])
33 48
    if @category.save
34 49
      respond_to do |format|
35 50
        format.html do
......
42 57
            content_tag('select', '<option></option>' + options_from_collection_for_select(@project.issue_categories, 'id', 'name', @category.id), :id => 'issue_category_id', :name => 'issue[category_id]')
43 58
          }
44 59
        end
60
        format.api { render :action => 'show', :status => :created, :location => issue_category_path(@category) }
45 61
      end
46 62
    else
47 63
      respond_to do |format|
......
49 65
        format.js do
50 66
          render(:update) {|page| page.alert(@category.errors.full_messages.join('\n')) }
51 67
        end
68
        format.api { render_validation_errors(@category) }
52 69
      end
53 70
    end
54 71
  end
......
58 75

  
59 76
  verify :method => :put, :only => :update
60 77
  def update
61
    if @category.update_attributes(params[:category])
62
      flash[:notice] = l(:notice_successful_update)
63
      redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project
78
    if @category.update_attributes(params[:issue_category])
79
      respond_to do |format|
80
        format.html {
81
          flash[:notice] = l(:notice_successful_update)
82
          redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project
83
        }
84
        format.api { head :ok }
85
      end
64 86
    else
65
      render :action => 'edit'
87
      respond_to do |format|
88
        format.html { render :action => 'edit' }
89
        format.api { render_validation_errors(@category) }
90
      end
66 91
    end
67 92
  end
68 93

  
69 94
  verify :method => :delete, :only => :destroy
70 95
  def destroy
71 96
    @issue_count = @category.issues.size
72
    if @issue_count == 0
73
      # No issue assigned to this category
74
      @category.destroy
75
      redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories'
76
      return
77
    elsif params[:todo]
78
      reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id]) if params[:todo] == 'reassign'
97
    if @issue_count == 0 || params[:todo] || api_request? 
98
      reassign_to = nil
99
      if params[:reassign_to_id] && (params[:todo] == 'reassign' || params[:todo].blank?)
100
        reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id])
101
      end
79 102
      @category.destroy(reassign_to)
80
      redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories'
103
      respond_to do |format|
104
        format.html { redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories' }
105
        format.api { head :ok }
106
      end
81 107
      return
82 108
    end
83 109
    @categories = @project.issue_categories - [@category]
trunk/app/models/issue_category.rb
23 23
  validates_presence_of :name
24 24
  validates_uniqueness_of :name, :scope => [:project_id]
25 25
  validates_length_of :name, :maximum => 30
26
  
27
  attr_protected :project_id
26 28

  
27 29
  named_scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
28 30

  
trunk/app/views/issue_categories/edit.html.erb
1 1
<h2><%=l(:label_issue_category)%></h2>
2 2

  
3
<% labelled_tabular_form_for :category, @category, :url => issue_category_path(@category), :html => {:method => :put} do |f| %>
3
<% labelled_tabular_form_for :issue_category, @category, :url => issue_category_path(@category), :html => {:method => :put} do |f| %>
4 4
<%= render :partial => 'issue_categories/form', :locals => { :f => f } %>
5 5
<%= submit_tag l(:button_save) %>
6 6
<% end %>
trunk/app/views/issue_categories/index.api.rsb
1
api.array :issue_categories, api_meta(:total_count => @categories.size) do
2
  @categories.each do |category|
3
    api.issue_category do
4
      api.id category.id
5
      api.project(:id => category.project_id, :name => category.project.name) unless category.project.nil?
6
      api.name category.name
7
      api.assigned_to(:id => category.assigned_to_id, :name => category.assigned_to.name) unless category.assigned_to.nil?
8
    end
9
  end
10
end
0 11

  
trunk/app/views/issue_categories/new.html.erb
1 1
<h2><%=l(:label_issue_category_new)%></h2>
2 2

  
3
<% labelled_tabular_form_for :category, @category, :url => project_issue_categories_path(@project) do |f| %>
3
<% labelled_tabular_form_for :issue_category, @category, :url => project_issue_categories_path(@project) do |f| %>
4 4
<%= render :partial => 'issue_categories/form', :locals => { :f => f } %>
5 5
<%= submit_tag l(:button_create) %>
6 6
<% end %>
trunk/app/views/issue_categories/show.api.rsb
1
api.issue_category do
2
  api.id @category.id
3
  api.project(:id => @category.project_id, :name => @category.project.name) unless @category.project.nil?
4
  api.name @category.name
5
  api.assigned_to(:id => @category.assigned_to_id, :name => @category.assigned_to.name) unless @category.assigned_to.nil?
6
end
0 7

  
trunk/lib/redmine.rb
58 58

  
59 59
  map.project_module :issue_tracking do |map|
60 60
    # Issue categories
61
    map.permission :manage_categories, {:projects => :settings, :issue_categories => [:new, :create, :edit, :update, :destroy]}, :require => :member
61
    map.permission :manage_categories, {:projects => :settings, :issue_categories => [:index, :show, :new, :create, :edit, :update, :destroy]}, :require => :member
62 62
    # Issues
63 63
    map.permission :view_issues, {:issues => [:index, :show],
64 64
                                  :auto_complete => [:issues],
trunk/test/functional/issue_categories_controller_test.rb
42 42
  def test_create
43 43
    @request.session[:user_id] = 2 # manager
44 44
    assert_difference 'IssueCategory.count' do
45
      post :create, :project_id => '1', :category => {:name => 'New category'}
45
      post :create, :project_id => '1', :issue_category => {:name => 'New category'}
46 46
    end
47 47
    assert_redirected_to '/projects/ecookbook/settings/categories'
48 48
    category = IssueCategory.find_by_name('New category')
......
52 52

  
53 53
  def test_create_failure
54 54
    @request.session[:user_id] = 2
55
    post :create, :project_id => '1', :category => {:name => ''}
55
    post :create, :project_id => '1', :issue_category => {:name => ''}
56 56
    assert_response :success
57 57
    assert_template 'new'
58 58
  end
......
66 66

  
67 67
  def test_update
68 68
    assert_no_difference 'IssueCategory.count' do
69
      put :update, :id => 2, :category => { :name => 'Testing' }
69
      put :update, :id => 2, :issue_category => { :name => 'Testing' }
70 70
    end
71 71
    assert_redirected_to '/projects/ecookbook/settings/categories'
72 72
    assert_equal 'Testing', IssueCategory.find(2).name
73 73
  end
74 74

  
75 75
  def test_update_failure
76
    put :update, :id => 2, :category => { :name => '' }
76
    put :update, :id => 2, :issue_category => { :name => '' }
77 77
    assert_response :success
78 78
    assert_template 'edit'
79 79
  end
80 80

  
81 81
  def test_update_not_found
82
    put :update, :id => 97, :category => { :name => 'Testing' }
82
    put :update, :id => 97, :issue_category => { :name => 'Testing' }
83 83
    assert_response 404
84 84
  end
85 85

  
trunk/test/integration/api_test/issue_categories_test.rb
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  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::IssueCategoriesTest < ActionController::IntegrationTest
21
  fixtures :projects, :users, :issue_categories, :issues,
22
           :roles,
23
           :member_roles,
24
           :members,
25
           :enabled_modules
26

  
27
  def setup
28
    Setting.rest_api_enabled = '1'
29
  end
30

  
31
  context "GET /projects/:project_id/issue_categories.xml" do
32
    should "return issue categories" do
33
      get '/projects/1/issue_categories.xml', {}, :authorization => credentials('jsmith')
34
      assert_response :success
35
      assert_equal 'application/xml', @response.content_type
36
      assert_tag :tag => 'issue_categories',
37
        :child => {:tag => 'issue_category', :child => {:tag => 'id', :content => '2'}}
38
    end
39
  end
40

  
41
  context "GET /issue_categories/2.xml" do
42
    should "return requested issue category" do
43
      get '/issue_categories/2.xml', {}, :authorization => credentials('jsmith')
44
      assert_response :success
45
      assert_equal 'application/xml', @response.content_type
46
      assert_tag :tag => 'issue_category',
47
        :child => {:tag => 'id', :content => '2'}
48
    end
49
  end
50

  
51
  context "POST /projects/:project_id/issue_categories.xml" do
52
    should "return create issue category" do
53
      assert_difference 'IssueCategory.count' do
54
        post '/projects/1/issue_categories.xml', {:issue_category => {:name => 'API'}}, :authorization => credentials('jsmith')
55
      end
56
      assert_response :created
57
      assert_equal 'application/xml', @response.content_type
58

  
59
      category = IssueCategory.first(:order => 'id DESC')
60
      assert_equal 'API', category.name
61
      assert_equal 1, category.project_id
62
    end
63

  
64
    context "with invalid parameters" do
65
      should "return errors" do
66
        assert_no_difference 'IssueCategory.count' do
67
          post '/projects/1/issue_categories.xml', {:issue_category => {:name => ''}}, :authorization => credentials('jsmith')
68
        end
69
        assert_response :unprocessable_entity
70
        assert_equal 'application/xml', @response.content_type
71

  
72
        assert_tag 'errors', :child => {:tag => 'error', :content => "Name can't be blank"}
73
      end
74
    end
75
  end
76

  
77
  context "PUT /issue_categories/2.xml" do
78
    context "with valid parameters" do
79
      should "update issue category" do
80
        assert_no_difference 'IssueCategory.count' do
81
          put '/issue_categories/2.xml', {:issue_category => {:name => 'API Update'}}, :authorization => credentials('jsmith')
82
        end
83
        assert_response :ok
84
        assert_equal 'API Update', IssueCategory.find(2).name
85
      end
86
    end
87

  
88
    context "with invalid parameters" do
89
      should "return errors" do
90
        assert_no_difference 'IssueCategory.count' do
91
          put '/issue_categories/2.xml', {:issue_category => {:name => ''}}, :authorization => credentials('jsmith')
92
        end
93
        assert_response :unprocessable_entity
94
        assert_equal 'application/xml', @response.content_type
95

  
96
        assert_tag 'errors', :child => {:tag => 'error', :content => "Name can't be blank"}
97
      end
98
    end
99
  end
100

  
101
  context "DELETE /issue_categories/1.xml" do
102
    should "destroy issue categories" do
103
      assert_difference 'IssueCategory.count', -1 do
104
        delete '/issue_categories/1.xml', {}, :authorization => credentials('jsmith')
105
      end
106
      assert_response :ok
107
      assert_nil IssueCategory.find_by_id(1)
108
    end
109
    
110
    should "reassign issues with :reassign_to_id param" do
111
      issue_count = Issue.count(:conditions => {:category_id => 1})
112
      assert issue_count > 0
113

  
114
      assert_difference 'IssueCategory.count', -1 do
115
        assert_difference 'Issue.count(:conditions => {:category_id => 2})', 3 do
116
          delete '/issue_categories/1.xml', {:reassign_to_id => 2}, :authorization => credentials('jsmith')
117
        end
118
      end
119
      assert_response :ok
120
      assert_nil IssueCategory.find_by_id(1)
121
    end
122
  end
123

  
124
  def credentials(user, password=nil)
125
    ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)
126
  end
127
end
0 128

  
trunk/test/integration/routing_test.rb
114 114
  end
115 115

  
116 116
  context "issue categories" do
117
    should_route :get, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
117
    should_route :get, "/projects/foo/issue_categories", :controller => 'issue_categories', :action => 'index', :project_id => 'foo'
118
    should_route :get, "/projects/foo/issue_categories.xml", :controller => 'issue_categories', :action => 'index', :project_id => 'foo', :format => 'xml'
119
    should_route :get, "/projects/foo/issue_categories.json", :controller => 'issue_categories', :action => 'index', :project_id => 'foo', :format => 'json'
118 120

  
119
    should_route :post, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
121
    should_route :get, "/projects/foo/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'foo'
122

  
123
    should_route :post, "/projects/foo/issue_categories", :controller => 'issue_categories', :action => 'create', :project_id => 'foo'
124
    should_route :post, "/projects/foo/issue_categories.xml", :controller => 'issue_categories', :action => 'create', :project_id => 'foo', :format => 'xml'
125
    should_route :post, "/projects/foo/issue_categories.json", :controller => 'issue_categories', :action => 'create', :project_id => 'foo', :format => 'json'
126

  
127
    should_route :get, "/issue_categories/1", :controller => 'issue_categories', :action => 'show', :id => '1'
128
    should_route :get, "/issue_categories/1.xml", :controller => 'issue_categories', :action => 'show', :id => '1', :format => 'xml'
129
    should_route :get, "/issue_categories/1.json", :controller => 'issue_categories', :action => 'show', :id => '1', :format => 'json'
130

  
131
    should_route :get, "/issue_categories/1/edit", :controller => 'issue_categories', :action => 'edit', :id => '1'
132

  
133
    should_route :put, "/issue_categories/1", :controller => 'issue_categories', :action => 'update', :id => '1'
134
    should_route :put, "/issue_categories/1.xml", :controller => 'issue_categories', :action => 'update', :id => '1', :format => 'xml'
135
    should_route :put, "/issue_categories/1.json", :controller => 'issue_categories', :action => 'update', :id => '1', :format => 'json'
136

  
137
    should_route :delete, "/issue_categories/1", :controller => 'issue_categories', :action => 'destroy', :id => '1'
138
    should_route :delete, "/issue_categories/1.xml", :controller => 'issue_categories', :action => 'destroy', :id => '1', :format => 'xml'
139
    should_route :delete, "/issue_categories/1.json", :controller => 'issue_categories', :action => 'destroy', :id => '1', :format => 'json'
120 140
  end
121 141

  
122 142
  context "issue relations" do

Also available in: Unified diff