##// END OF EJS Templates
Resourcified documents....
Jean-Philippe Lang -
r7890:c3c2a4afe008
parent child
Show More
@@ -1,79 +1,89
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2011 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 DocumentsController < ApplicationController
19 19 default_search_scope :documents
20 20 model_object Document
21 before_filter :find_project_by_project_id, :only => [:index, :new]
22 before_filter :find_model_object, :except => [:index, :new]
23 before_filter :find_project_from_association, :except => [:index, :new]
21 before_filter :find_project_by_project_id, :only => [:index, :new, :create]
22 before_filter :find_model_object, :except => [:index, :new, :create]
23 before_filter :find_project_from_association, :except => [:index, :new, :create]
24 24 before_filter :authorize
25 25
26 26 helper :attachments
27 27
28 28 def index
29 29 @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
30 30 documents = @project.documents.find :all, :include => [:attachments, :category]
31 31 case @sort_by
32 32 when 'date'
33 33 @grouped = documents.group_by {|d| d.updated_on.to_date }
34 34 when 'title'
35 35 @grouped = documents.group_by {|d| d.title.first.upcase}
36 36 when 'author'
37 37 @grouped = documents.select{|d| d.attachments.any?}.group_by {|d| d.attachments.last.author}
38 38 else
39 39 @grouped = documents.group_by(&:category)
40 40 end
41 41 @document = @project.documents.build
42 42 render :layout => false if request.xhr?
43 43 end
44 44
45 45 def show
46 46 @attachments = @document.attachments.find(:all, :order => "created_on DESC")
47 47 end
48 48
49 49 def new
50 50 @document = @project.documents.build(params[:document])
51 end
52
53 def create
54 @document = @project.documents.build(params[:document])
51 55 if request.post? and @document.save
52 56 attachments = Attachment.attach_files(@document, params[:attachments])
53 57 render_attachment_warning_if_needed(@document)
54 58 flash[:notice] = l(:notice_successful_create)
55 59 redirect_to :action => 'index', :project_id => @project
60 else
61 render :action => 'new'
56 62 end
57 63 end
58 64
59 65 def edit
60 @categories = DocumentCategory.active #TODO: use it in the views
61 if request.post? and @document.update_attributes(params[:document])
66 end
67
68 def update
69 if request.put? and @document.update_attributes(params[:document])
62 70 flash[:notice] = l(:notice_successful_update)
63 71 redirect_to :action => 'show', :id => @document
72 else
73 render :action => 'edit'
64 74 end
65 75 end
66 76
67 77 def destroy
68 @document.destroy
78 @document.destroy if request.delete?
69 79 redirect_to :controller => 'documents', :action => 'index', :project_id => @project
70 80 end
71 81
72 82 def add_attachment
73 83 attachments = Attachment.attach_files(@document, params[:attachments])
74 84 render_attachment_warning_if_needed(@document)
75 85
76 86 Mailer.deliver_attachments_added(attachments[:files]) if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added')
77 87 redirect_to :action => 'show', :id => @document
78 88 end
79 89 end
@@ -1,6 +1,6
1 <h4><%= link_to h(document.title), :controller => 'documents', :action => 'show', :id => document %></h4>
1 <h4><%= link_to h(document.title), document_path(document) %></h4>
2 2 <p><em><%= format_time(document.updated_on) %></em></p>
3 3
4 4 <div class="wiki">
5 5 <%= textilizable(truncate_lines(document.description), :object => document) %>
6 6 </div>
@@ -1,15 +1,15
1 <%= error_messages_for 'document' %>
2 <div class="box">
3 <!--[form:document]-->
4 <p><label for="document_category_id"><%=l(:field_category)%></label>
5 <%= select('document', 'category_id', DocumentCategory.active.collect {|c| [c.name, c.id]}) %></p>
1 <%= f.error_messages %>
6 2
7 <p><label for="document_title"><%=l(:field_title)%> <span class="required">*</span></label>
8 <%= text_field 'document', 'title', :size => 60 %></p>
9
10 <p><label for="document_description"><%=l(:field_description)%></label>
11 <%= text_area 'document', 'description', :cols => 60, :rows => 15, :class => 'wiki-edit' %></p>
12 <!--[eoform:document]-->
3 <div class="box tabular">
4 <p><%= f.select :category_id, DocumentCategory.active.collect {|c| [c.name, c.id]} %></p>
5 <p><%= f.text_field :title, :required => true, :size => 60 %></p>
6 <p><%= f.text_area :description, :cols => 60, :rows => 15, :class => 'wiki-edit' %></p>
13 7 </div>
14 8
15 9 <%= wikitoolbar_for 'document_description' %>
10
11 <% if @document.new_record? %>
12 <div class="box tabular">
13 <p><label><%=l(:label_attachment_plural)%></label><%= render :partial => 'attachments/form' %></p>
14 </div>
15 <% end %>
@@ -1,8 +1,8
1 1 <h2><%=l(:label_document)%></h2>
2 2
3 <% form_tag({:action => 'edit', :id => @document}, :class => "tabular") do %>
4 <%= render :partial => 'form' %>
5 <%= submit_tag l(:button_save) %>
3 <% labelled_form_for @document do |f| %>
4 <%= render :partial => 'form', :locals => {:f => f} %>
5 <p><%= submit_tag l(:button_save) %></p>
6 6 <% end %>
7 7
8 8
@@ -1,39 +1,36
1 1 <div class="contextual">
2 <%= link_to_if_authorized l(:label_document_new),
3 {:controller => 'documents', :action => 'new', :project_id => @project},
4 :class => 'icon icon-add',
5 :onclick => 'Element.show("add-document"); Form.Element.focus("document_title"); return false;' %>
2 <%= link_to l(:label_document_new), new_project_document_path(@project), :class => 'icon icon-add',
3 :onclick => 'Element.show("add-document"); Form.Element.focus("document_title"); return false;' if User.current.allowed_to?(:manage_documents, @project) %>
6 4 </div>
7 5
8 6 <div id="add-document" style="display:none;">
9 7 <h2><%=l(:label_document_new)%></h2>
10 <% form_tag({:controller => 'documents', :action => 'new', :project_id => @project}, :class => "tabular", :multipart => true) do %>
11 <%= render :partial => 'documents/form' %>
12 <div class="box">
13 <p><label><%=l(:label_attachment_plural)%></label><%= render :partial => 'attachments/form' %></p>
14 </div>
8 <% labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
9 <%= render :partial => 'form', :locals => {:f => f} %>
10 <p>
15 11 <%= submit_tag l(:button_create) %>
16 12 <%= link_to l(:button_cancel), "#", :onclick => 'Element.hide("add-document")' %>
13 </p>
17 14 <% end %>
18 15 </div>
19 16
20 17 <h2><%=l(:label_document_plural)%></h2>
21 18
22 19 <% if @grouped.empty? %><p class="nodata"><%= l(:label_no_data) %></p><% end %>
23 20
24 21 <% @grouped.keys.sort.each do |group| %>
25 22 <h3><%= group %></h3>
26 23 <%= render :partial => 'documents/document', :collection => @grouped[group] %>
27 24 <% end %>
28 25
29 26 <% content_for :sidebar do %>
30 27 <h3><%= l(:label_sort_by, '') %></h3>
31 28 <% form_tag({}, :method => :get) do %>
32 29 <label><%= radio_button_tag 'sort_by', 'category', (@sort_by == 'category'), :onclick => 'this.form.submit();' %> <%= l(:field_category) %></label><br />
33 30 <label><%= radio_button_tag 'sort_by', 'date', (@sort_by == 'date'), :onclick => 'this.form.submit();' %> <%= l(:label_date) %></label><br />
34 31 <label><%= radio_button_tag 'sort_by', 'title', (@sort_by == 'title'), :onclick => 'this.form.submit();' %> <%= l(:field_title) %></label><br />
35 32 <label><%= radio_button_tag 'sort_by', 'author', (@sort_by == 'author'), :onclick => 'this.form.submit();' %> <%= l(:field_author) %></label>
36 33 <% end %>
37 34 <% end %>
38 35
39 36 <% html_title(l(:label_document_plural)) -%>
@@ -1,13 +1,6
1 1 <h2><%=l(:label_document_new)%></h2>
2 2
3 <% form_tag({:controller => 'documents', :action => 'new', :project_id => @project}, :class => "tabular", :multipart => true) do %>
4 <%= render :partial => 'documents/form' %>
5
6 <div class="box">
7 <p><label><%=l(:label_attachment_plural)%></label><%= render :partial => 'attachments/form' %></p>
8 </div>
9
10 <%= submit_tag l(:button_create) %>
3 <% labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
4 <%= render :partial => 'form', :locals => {:f => f} %>
5 <p><%= submit_tag l(:button_create) %></p>
11 6 <% end %>
12
13
@@ -1,32 +1,34
1 1 <div class="contextual">
2 <%= link_to_if_authorized l(:button_edit), {:controller => 'documents', :action => 'edit', :id => @document}, :class => 'icon icon-edit', :accesskey => accesskey(:edit) %>
3 <%= link_to_if_authorized l(:button_delete), {:controller => 'documents', :action => 'destroy', :id => @document}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
2 <% if User.current.allowed_to?(:manage_documents, @project) %>
3 <%= link_to l(:button_edit), edit_document_path(@document), :class => 'icon icon-edit', :accesskey => accesskey(:edit) %>
4 <%= link_to l(:button_delete), document_path(@document), :confirm => l(:text_are_you_sure), :method => :delete, :class => 'icon icon-del' %>
5 <% end %>
4 6 </div>
5 7
6 8 <h2><%=h @document.title %></h2>
7 9
8 10 <p><em><%=h @document.category.name %><br />
9 11 <%= format_date @document.created_on %></em></p>
10 12 <div class="wiki">
11 13 <%= textilizable @document.description, :attachments => @document.attachments %>
12 14 </div>
13 15
14 16 <h3><%= l(:label_attachment_plural) %></h3>
15 17 <%= link_to_attachments @document %>
16 18
17 19 <% if authorize_for('documents', 'add_attachment') %>
18 20 <p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",
19 21 :id => 'attach_files_link' %></p>
20 22 <% form_tag({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
21 23 <div class="box">
22 24 <p><%= render :partial => 'attachments/form' %></p>
23 25 </div>
24 26 <%= submit_tag l(:button_add) %>
25 27 <% end %>
26 28 <% end %>
27 29
28 30 <% html_title @document.title -%>
29 31
30 32 <% content_for :header_tags do %>
31 33 <%= stylesheet_link_tag 'scm' %>
32 34 <% end %>
@@ -1,258 +1,245
1 1 ActionController::Routing::Routes.draw do |map|
2 2 # Add your own custom routes here.
3 3 # The priority is based upon order of creation: first created -> highest priority.
4 4
5 5 # Here's a sample route:
6 6 # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
7 7 # Keep in mind you can assign values other than :controller and :action
8 8
9 9 map.home '', :controller => 'welcome'
10 10
11 11 map.signin 'login', :controller => 'account', :action => 'login'
12 12 map.signout 'logout', :controller => 'account', :action => 'logout'
13 13
14 14 map.connect 'roles/workflow/:id/:role_id/:tracker_id', :controller => 'roles', :action => 'workflow'
15 15 map.connect 'help/:ctrl/:page', :controller => 'help'
16 16
17 17 map.with_options :controller => 'time_entry_reports', :action => 'report',:conditions => {:method => :get} do |time_report|
18 18 time_report.connect 'projects/:project_id/issues/:issue_id/time_entries/report'
19 19 time_report.connect 'projects/:project_id/issues/:issue_id/time_entries/report.:format'
20 20 time_report.connect 'projects/:project_id/time_entries/report'
21 21 time_report.connect 'projects/:project_id/time_entries/report.:format'
22 22 time_report.connect 'time_entries/report'
23 23 time_report.connect 'time_entries/report.:format'
24 24 end
25 25
26 26 map.bulk_edit_time_entry 'time_entries/bulk_edit',
27 27 :controller => 'timelog', :action => 'bulk_edit', :conditions => { :method => :get }
28 28 map.bulk_update_time_entry 'time_entries/bulk_edit',
29 29 :controller => 'timelog', :action => 'bulk_update', :conditions => { :method => :post }
30 30 map.time_entries_context_menu '/time_entries/context_menu',
31 31 :controller => 'context_menus', :action => 'time_entries'
32 32 # TODO: wasteful since this is also nested under issues, projects, and projects/issues
33 33 map.resources :time_entries, :controller => 'timelog'
34 34
35 35 map.connect 'projects/:id/wiki', :controller => 'wikis', :action => 'edit', :conditions => {:method => :post}
36 36 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :get}
37 37 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :post}
38 38
39 39 map.with_options :controller => 'messages' do |messages_routes|
40 40 messages_routes.with_options :conditions => {:method => :get} do |messages_views|
41 41 messages_views.connect 'boards/:board_id/topics/new', :action => 'new'
42 42 messages_views.connect 'boards/:board_id/topics/:id', :action => 'show'
43 43 messages_views.connect 'boards/:board_id/topics/:id/edit', :action => 'edit'
44 44 end
45 45 messages_routes.with_options :conditions => {:method => :post} do |messages_actions|
46 46 messages_actions.connect 'boards/:board_id/topics/new', :action => 'new'
47 47 messages_actions.connect 'boards/:board_id/topics/:id/replies', :action => 'reply'
48 48 messages_actions.connect 'boards/:board_id/topics/:id/:action', :action => /edit|destroy/
49 49 end
50 50 end
51 51
52 52 map.with_options :controller => 'boards' do |board_routes|
53 53 board_routes.with_options :conditions => {:method => :get} do |board_views|
54 54 board_views.connect 'projects/:project_id/boards', :action => 'index'
55 55 board_views.connect 'projects/:project_id/boards/new', :action => 'new'
56 56 board_views.connect 'projects/:project_id/boards/:id', :action => 'show'
57 57 board_views.connect 'projects/:project_id/boards/:id.:format', :action => 'show'
58 58 board_views.connect 'projects/:project_id/boards/:id/edit', :action => 'edit'
59 59 end
60 60 board_routes.with_options :conditions => {:method => :post} do |board_actions|
61 61 board_actions.connect 'projects/:project_id/boards', :action => 'new'
62 62 board_actions.connect 'projects/:project_id/boards/:id/:action', :action => /edit|destroy/
63 63 end
64 64 end
65 65
66 map.with_options :controller => 'documents' do |document_routes|
67 document_routes.with_options :conditions => {:method => :get} do |document_views|
68 document_views.connect 'projects/:project_id/documents', :action => 'index'
69 document_views.connect 'projects/:project_id/documents/new', :action => 'new'
70 document_views.connect 'documents/:id', :action => 'show'
71 document_views.connect 'documents/:id/edit', :action => 'edit'
72 end
73 document_routes.with_options :conditions => {:method => :post} do |document_actions|
74 document_actions.connect 'projects/:project_id/documents', :action => 'new'
75 document_actions.connect 'documents/:id/:action', :action => /destroy|edit/
76 end
77 end
78
79 66 map.resources :issue_moves, :only => [:new, :create], :path_prefix => '/issues', :as => 'move'
80 67 map.resources :queries, :except => [:show]
81 68
82 69 # Misc issue routes. TODO: move into resources
83 70 map.auto_complete_issues '/issues/auto_complete', :controller => 'auto_completes', :action => 'issues'
84 71 map.preview_issue '/issues/preview/:id', :controller => 'previews', :action => 'issue' # TODO: would look nicer as /issues/:id/preview
85 72 map.issues_context_menu '/issues/context_menu', :controller => 'context_menus', :action => 'issues'
86 73 map.issue_changes '/issues/changes', :controller => 'journals', :action => 'index'
87 74 map.bulk_edit_issue 'issues/bulk_edit', :controller => 'issues', :action => 'bulk_edit', :conditions => { :method => :get }
88 75 map.bulk_update_issue 'issues/bulk_edit', :controller => 'issues', :action => 'bulk_update', :conditions => { :method => :post }
89 76 map.quoted_issue '/issues/:id/quoted', :controller => 'journals', :action => 'new', :id => /\d+/, :conditions => { :method => :post }
90 77 map.connect '/issues/:id/destroy', :controller => 'issues', :action => 'destroy', :conditions => { :method => :post } # legacy
91 78
92 79 map.with_options :controller => 'gantts', :action => 'show' do |gantts_routes|
93 80 gantts_routes.connect '/projects/:project_id/issues/gantt'
94 81 gantts_routes.connect '/projects/:project_id/issues/gantt.:format'
95 82 gantts_routes.connect '/issues/gantt.:format'
96 83 end
97 84
98 85 map.with_options :controller => 'calendars', :action => 'show' do |calendars_routes|
99 86 calendars_routes.connect '/projects/:project_id/issues/calendar'
100 87 calendars_routes.connect '/issues/calendar'
101 88 end
102 89
103 90 map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports|
104 91 reports.connect 'projects/:id/issues/report', :action => 'issue_report'
105 92 reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details'
106 93 end
107 94
108 95 # Following two routes conflict with the resources because #index allows POST
109 96 map.connect '/issues', :controller => 'issues', :action => 'index', :conditions => { :method => :post }
110 97 map.connect '/issues/create', :controller => 'issues', :action => 'index', :conditions => { :method => :post }
111 98
112 99 map.resources :issues, :member => { :edit => :post }, :collection => {} do |issues|
113 100 issues.resources :time_entries, :controller => 'timelog'
114 101 issues.resources :relations, :shallow => true, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy]
115 102 end
116 103
117 104 map.resources :issues, :path_prefix => '/projects/:project_id', :collection => { :create => :post } do |issues|
118 105 issues.resources :time_entries, :controller => 'timelog'
119 106 end
120 107
121 108 map.connect 'projects/:id/members/new', :controller => 'members', :action => 'new'
122 109
123 110 map.with_options :controller => 'users' do |users|
124 111 users.connect 'users/:id/edit/:tab', :action => 'edit', :tab => nil, :conditions => {:method => :get}
125 112
126 113 users.with_options :conditions => {:method => :post} do |user_actions|
127 114 user_actions.connect 'users/:id/memberships', :action => 'edit_membership'
128 115 user_actions.connect 'users/:id/memberships/:membership_id', :action => 'edit_membership'
129 116 user_actions.connect 'users/:id/memberships/:membership_id/destroy', :action => 'destroy_membership'
130 117 end
131 118 end
132 119
133 120 map.resources :users, :member => {
134 121 :edit_membership => :post,
135 122 :destroy_membership => :post
136 123 }
137 124
138 125 # For nice "roadmap" in the url for the index action
139 126 map.connect 'projects/:project_id/roadmap', :controller => 'versions', :action => 'index'
140 127
141 128 map.all_news 'news', :controller => 'news', :action => 'index'
142 129 map.formatted_all_news 'news.:format', :controller => 'news', :action => 'index'
143 130 map.preview_news '/news/preview', :controller => 'previews', :action => 'news'
144 131 map.connect 'news/:id/comments', :controller => 'comments', :action => 'create', :conditions => {:method => :post}
145 132 map.connect 'news/:id/comments/:comment_id', :controller => 'comments', :action => 'destroy', :conditions => {:method => :delete}
146 133
147 134 map.resources :projects, :member => {
148 135 :copy => [:get, :post],
149 136 :settings => :get,
150 137 :modules => :post,
151 138 :archive => :post,
152 139 :unarchive => :post
153 140 } do |project|
154 141 project.resource :project_enumerations, :as => 'enumerations', :only => [:update, :destroy]
155 142 project.resources :files, :only => [:index, :new, :create]
156 143 project.resources :versions, :shallow => true, :collection => {:close_completed => :put}, :member => {:status_by => :post}
157 144 project.resources :news, :shallow => true
158 145 project.resources :time_entries, :controller => 'timelog', :path_prefix => 'projects/:project_id'
159 146 project.resources :queries, :only => [:new, :create]
160 147 project.resources :issue_categories, :shallow => true
148 project.resources :documents, :shallow => true, :member => {:add_attachment => :post}
161 149
162 150 project.wiki_start_page 'wiki', :controller => 'wiki', :action => 'show', :conditions => {:method => :get}
163 151 project.wiki_index 'wiki/index', :controller => 'wiki', :action => 'index', :conditions => {:method => :get}
164 152 project.wiki_diff 'wiki/:id/diff/:version', :controller => 'wiki', :action => 'diff', :version => nil
165 153 project.wiki_diff 'wiki/:id/diff/:version/vs/:version_from', :controller => 'wiki', :action => 'diff'
166 154 project.wiki_annotate 'wiki/:id/annotate/:version', :controller => 'wiki', :action => 'annotate'
167 155 project.resources :wiki, :except => [:new, :create], :member => {
168 156 :rename => [:get, :post],
169 157 :history => :get,
170 158 :preview => :any,
171 159 :protect => :post,
172 160 :add_attachment => :post
173 161 }, :collection => {
174 162 :export => :get,
175 163 :date_index => :get
176 164 }
177 165
178 166 end
179 167
180 168 # Destroy uses a get request to prompt the user before the actual DELETE request
181 169 map.project_destroy_confirm 'projects/:id/destroy', :controller => 'projects', :action => 'destroy', :conditions => {:method => :get}
182 170
183 171 # TODO: port to be part of the resources route(s)
184 172 map.with_options :controller => 'projects' do |project_mapper|
185 173 project_mapper.with_options :conditions => {:method => :get} do |project_views|
186 174 project_views.connect 'projects/:id/settings/:tab', :controller => 'projects', :action => 'settings'
187 175 project_views.connect 'projects/:project_id/issues/:copy_from/copy', :controller => 'issues', :action => 'new'
188 176 end
189 177 end
190 178
191 179 map.with_options :controller => 'activities', :action => 'index', :conditions => {:method => :get} do |activity|
192 180 activity.connect 'projects/:id/activity'
193 181 activity.connect 'projects/:id/activity.:format'
194 182 activity.connect 'activity', :id => nil
195 183 activity.connect 'activity.:format', :id => nil
196 184 end
197 185
198 186 map.with_options :controller => 'repositories' do |repositories|
199 187 repositories.with_options :conditions => {:method => :get} do |repository_views|
200 188 repository_views.connect 'projects/:id/repository', :action => 'show'
201 189 repository_views.connect 'projects/:id/repository/edit', :action => 'edit'
202 190 repository_views.connect 'projects/:id/repository/statistics', :action => 'stats'
203 191 repository_views.connect 'projects/:id/repository/revisions', :action => 'revisions'
204 192 repository_views.connect 'projects/:id/repository/revisions.:format', :action => 'revisions'
205 193 repository_views.connect 'projects/:id/repository/revisions/:rev', :action => 'revision'
206 194 repository_views.connect 'projects/:id/repository/revisions/:rev/diff', :action => 'diff'
207 195 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format', :action => 'diff'
208 196 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path', :action => 'entry', :format => 'raw', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
209 197 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
210 198 repository_views.connect 'projects/:id/repository/raw/*path', :action => 'entry', :format => 'raw'
211 199 # TODO: why the following route is required?
212 200 repository_views.connect 'projects/:id/repository/entry/*path', :action => 'entry'
213 201 repository_views.connect 'projects/:id/repository/:action/*path'
214 202 end
215 203
216 204 repositories.connect 'projects/:id/repository/:action', :conditions => {:method => :post}
217 205 end
218 206
219 207 map.resources :attachments, :only => [:show, :destroy]
220 208 # additional routes for having the file name at the end of url
221 209 map.connect 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/
222 210 map.connect 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/
223 211
224 212 map.resources :groups, :member => {:autocomplete_for_user => :get}
225 213 map.group_users 'groups/:id/users', :controller => 'groups', :action => 'add_users', :id => /\d+/, :conditions => {:method => :post}
226 214 map.group_user 'groups/:id/users/:user_id', :controller => 'groups', :action => 'remove_user', :id => /\d+/, :conditions => {:method => :delete}
227 215
228 216 map.resources :trackers, :except => :show
229 217 map.resources :issue_statuses, :except => :show, :collection => {:update_issue_done_ratio => :post}
230 218
231 219 #left old routes at the bottom for backwards compat
232 220 map.connect 'projects/:project_id/issues/:action', :controller => 'issues'
233 map.connect 'projects/:project_id/documents/:action', :controller => 'documents'
234 221 map.connect 'projects/:project_id/boards/:action/:id', :controller => 'boards'
235 222 map.connect 'boards/:board_id/topics/:action/:id', :controller => 'messages'
236 223 map.connect 'wiki/:id/:page/:action', :page => nil, :controller => 'wiki'
237 224 map.connect 'projects/:project_id/news/:action', :controller => 'news'
238 225 map.connect 'projects/:project_id/timelog/:action/:id', :controller => 'timelog', :project_id => /.+/
239 226 map.with_options :controller => 'repositories' do |omap|
240 227 omap.repositories_show 'repositories/browse/:id/*path', :action => 'browse'
241 228 omap.repositories_changes 'repositories/changes/:id/*path', :action => 'changes'
242 229 omap.repositories_diff 'repositories/diff/:id/*path', :action => 'diff'
243 230 omap.repositories_entry 'repositories/entry/:id/*path', :action => 'entry'
244 231 omap.repositories_entry 'repositories/annotate/:id/*path', :action => 'annotate'
245 232 omap.connect 'repositories/revision/:id/:rev', :action => 'revision'
246 233 end
247 234
248 235 map.with_options :controller => 'sys' do |sys|
249 236 sys.connect 'sys/projects.:format', :action => 'projects', :conditions => {:method => :get}
250 237 sys.connect 'sys/projects/:id/repository.:format', :action => 'create_project_repository', :conditions => {:method => :post}
251 238 end
252 239
253 240 # Install the default route as the lowest priority.
254 241 map.connect ':controller/:action/:id'
255 242 map.connect 'robots.txt', :controller => 'welcome', :action => 'robots'
256 243 # Used for OpenID
257 244 map.root :controller => 'account', :action => 'login'
258 245 end
@@ -1,237 +1,237
1 1 require 'redmine/access_control'
2 2 require 'redmine/menu_manager'
3 3 require 'redmine/activity'
4 4 require 'redmine/search'
5 5 require 'redmine/custom_field_format'
6 6 require 'redmine/mime_type'
7 7 require 'redmine/core_ext'
8 8 require 'redmine/themes'
9 9 require 'redmine/hook'
10 10 require 'redmine/plugin'
11 11 require 'redmine/notifiable'
12 12 require 'redmine/wiki_formatting'
13 13 require 'redmine/scm/base'
14 14
15 15 begin
16 16 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
17 17 rescue LoadError
18 18 # RMagick is not available
19 19 end
20 20
21 21 if RUBY_VERSION < '1.9'
22 22 require 'faster_csv'
23 23 else
24 24 require 'csv'
25 25 FCSV = CSV
26 26 end
27 27
28 28 Redmine::Scm::Base.add "Subversion"
29 29 Redmine::Scm::Base.add "Darcs"
30 30 Redmine::Scm::Base.add "Mercurial"
31 31 Redmine::Scm::Base.add "Cvs"
32 32 Redmine::Scm::Base.add "Bazaar"
33 33 Redmine::Scm::Base.add "Git"
34 34 Redmine::Scm::Base.add "Filesystem"
35 35
36 36 Redmine::CustomFieldFormat.map do |fields|
37 37 fields.register Redmine::CustomFieldFormat.new('string', :label => :label_string, :order => 1)
38 38 fields.register Redmine::CustomFieldFormat.new('text', :label => :label_text, :order => 2)
39 39 fields.register Redmine::CustomFieldFormat.new('int', :label => :label_integer, :order => 3)
40 40 fields.register Redmine::CustomFieldFormat.new('float', :label => :label_float, :order => 4)
41 41 fields.register Redmine::CustomFieldFormat.new('list', :label => :label_list, :order => 5)
42 42 fields.register Redmine::CustomFieldFormat.new('date', :label => :label_date, :order => 6)
43 43 fields.register Redmine::CustomFieldFormat.new('bool', :label => :label_boolean, :order => 7)
44 44 fields.register Redmine::CustomFieldFormat.new('user', :label => :label_user, :only => %w(Issue TimeEntry Version Project), :edit_as => 'list', :order => 8)
45 45 fields.register Redmine::CustomFieldFormat.new('version', :label => :label_version, :only => %w(Issue TimeEntry Version Project), :edit_as => 'list', :order => 9)
46 46 end
47 47
48 48 # Permissions
49 49 Redmine::AccessControl.map do |map|
50 50 map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true
51 51 map.permission :search_project, {:search => :index}, :public => true
52 52 map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin
53 53 map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member
54 54 map.permission :select_project_modules, {:projects => :modules}, :require => :member
55 55 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy, :autocomplete_for_member]}, :require => :member
56 56 map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
57 57 map.permission :add_subprojects, {:projects => [:new, :create]}, :require => :member
58 58
59 59 map.project_module :issue_tracking do |map|
60 60 # Issue categories
61 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],
65 65 :context_menus => [:issues],
66 66 :versions => [:index, :show, :status_by],
67 67 :journals => [:index, :diff],
68 68 :queries => :index,
69 69 :reports => [:issue_report, :issue_report_details]}
70 70 map.permission :add_issues, {:issues => [:new, :create, :update_form]}
71 71 map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]}
72 72 map.permission :manage_issue_relations, {:issue_relations => [:index, :show, :create, :destroy]}
73 73 map.permission :manage_subtasks, {}
74 74 map.permission :set_issues_private, {}
75 75 map.permission :set_own_issues_private, {}, :require => :loggedin
76 76 map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new]}
77 77 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
78 78 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
79 79 map.permission :move_issues, {:issue_moves => [:new, :create]}, :require => :loggedin
80 80 map.permission :delete_issues, {:issues => :destroy}, :require => :member
81 81 # Queries
82 82 map.permission :manage_public_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :member
83 83 map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
84 84 # Watchers
85 85 map.permission :view_issue_watchers, {}
86 86 map.permission :add_issue_watchers, {:watchers => :new}
87 87 map.permission :delete_issue_watchers, {:watchers => :destroy}
88 88 end
89 89
90 90 map.project_module :time_tracking do |map|
91 91 map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
92 92 map.permission :view_time_entries, :timelog => [:index, :show], :time_entry_reports => [:report]
93 93 map.permission :edit_time_entries, {:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
94 94 map.permission :edit_own_time_entries, {:timelog => [:edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
95 95 map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
96 96 end
97 97
98 98 map.project_module :news do |map|
99 99 map.permission :manage_news, {:news => [:new, :create, :edit, :update, :destroy], :comments => [:destroy]}, :require => :member
100 100 map.permission :view_news, {:news => [:index, :show]}, :public => true
101 101 map.permission :comment_news, {:comments => :create}
102 102 end
103 103
104 104 map.project_module :documents do |map|
105 map.permission :manage_documents, {:documents => [:new, :edit, :destroy, :add_attachment]}, :require => :loggedin
105 map.permission :manage_documents, {:documents => [:new, :create, :edit, :update, :destroy, :add_attachment]}, :require => :loggedin
106 106 map.permission :view_documents, :documents => [:index, :show, :download]
107 107 end
108 108
109 109 map.project_module :files do |map|
110 110 map.permission :manage_files, {:files => [:new, :create]}, :require => :loggedin
111 111 map.permission :view_files, :files => :index, :versions => :download
112 112 end
113 113
114 114 map.project_module :wiki do |map|
115 115 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
116 116 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
117 117 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
118 118 map.permission :view_wiki_pages, :wiki => [:index, :show, :special, :date_index]
119 119 map.permission :export_wiki_pages, :wiki => [:export]
120 120 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
121 121 map.permission :edit_wiki_pages, :wiki => [:edit, :update, :preview, :add_attachment]
122 122 map.permission :delete_wiki_pages_attachments, {}
123 123 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
124 124 end
125 125
126 126 map.project_module :repository do |map|
127 127 map.permission :manage_repository, {:repositories => [:edit, :committers, :destroy]}, :require => :member
128 128 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
129 129 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
130 130 map.permission :commit_access, {}
131 131 end
132 132
133 133 map.project_module :boards do |map|
134 134 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
135 135 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
136 136 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
137 137 map.permission :edit_messages, {:messages => :edit}, :require => :member
138 138 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
139 139 map.permission :delete_messages, {:messages => :destroy}, :require => :member
140 140 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
141 141 end
142 142
143 143 map.project_module :calendar do |map|
144 144 map.permission :view_calendar, :calendars => [:show, :update]
145 145 end
146 146
147 147 map.project_module :gantt do |map|
148 148 map.permission :view_gantt, :gantts => [:show, :update]
149 149 end
150 150 end
151 151
152 152 Redmine::MenuManager.map :top_menu do |menu|
153 153 menu.push :home, :home_path
154 154 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
155 155 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
156 156 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
157 157 menu.push :help, Redmine::Info.help_url, :last => true
158 158 end
159 159
160 160 Redmine::MenuManager.map :account_menu do |menu|
161 161 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
162 162 menu.push :register, { :controller => 'account', :action => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
163 163 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
164 164 menu.push :logout, :signout_path, :if => Proc.new { User.current.logged? }
165 165 end
166 166
167 167 Redmine::MenuManager.map :application_menu do |menu|
168 168 # Empty
169 169 end
170 170
171 171 Redmine::MenuManager.map :admin_menu do |menu|
172 172 menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
173 173 menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
174 174 menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
175 175 menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
176 176 menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
177 177 menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
178 178 :html => {:class => 'issue_statuses'}
179 179 menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
180 180 menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
181 181 :html => {:class => 'custom_fields'}
182 182 menu.push :enumerations, {:controller => 'enumerations'}
183 183 menu.push :settings, {:controller => 'settings'}
184 184 menu.push :ldap_authentication, {:controller => 'ldap_auth_sources', :action => 'index'},
185 185 :html => {:class => 'server_authentication'}
186 186 menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
187 187 menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
188 188 end
189 189
190 190 Redmine::MenuManager.map :project_menu do |menu|
191 191 menu.push :overview, { :controller => 'projects', :action => 'show' }
192 192 menu.push :activity, { :controller => 'activities', :action => 'index' }
193 193 menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id,
194 194 :if => Proc.new { |p| p.shared_versions.any? }
195 195 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
196 196 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
197 197 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
198 198 menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
199 199 menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
200 200 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
201 201 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
202 202 menu.push :wiki, { :controller => 'wiki', :action => 'show', :id => nil }, :param => :project_id,
203 203 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
204 204 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
205 205 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
206 206 menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural, :param => :project_id
207 207 menu.push :repository, { :controller => 'repositories', :action => 'show' },
208 208 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
209 209 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
210 210 end
211 211
212 212 Redmine::Activity.map do |activity|
213 213 activity.register :issues, :class_name => %w(Issue Journal)
214 214 activity.register :changesets
215 215 activity.register :news
216 216 activity.register :documents, :class_name => %w(Document Attachment)
217 217 activity.register :files, :class_name => 'Attachment'
218 218 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
219 219 activity.register :messages, :default => false
220 220 activity.register :time_entries, :default => false
221 221 end
222 222
223 223 Redmine::Search.map do |search|
224 224 search.register :issues
225 225 search.register :news
226 226 search.register :documents
227 227 search.register :changesets
228 228 search.register :wiki_pages
229 229 search.register :messages
230 230 search.register :projects
231 231 end
232 232
233 233 Redmine::WikiFormatting.map do |format|
234 234 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
235 235 end
236 236
237 237 ActionView::Template.register_template_handler :rsb, Redmine::Views::ApiTemplateHandler
@@ -1,144 +1,151
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2011 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 DocumentsControllerTest < ActionController::TestCase
21 21 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :documents, :enumerations
22 22
23 23 def setup
24 24 User.current = nil
25 25 end
26 26
27 27 def test_index
28 28 # Sets a default category
29 29 e = Enumeration.find_by_name('Technical documentation')
30 30 e.update_attributes(:is_default => true)
31 31
32 32 get :index, :project_id => 'ecookbook'
33 33 assert_response :success
34 34 assert_template 'index'
35 35 assert_not_nil assigns(:grouped)
36 36
37 37 # Default category selected in the new document form
38 38 assert_tag :select, :attributes => {:name => 'document[category_id]'},
39 39 :child => {:tag => 'option', :attributes => {:selected => 'selected'},
40 40 :content => 'Technical documentation'}
41 41
42 42 assert ! DocumentCategory.find(16).active?
43 43 assert_no_tag :option, :attributes => {:value => '16'},
44 44 :parent => {:tag => 'select', :attributes => {:id => 'document_category_id'} }
45 45 end
46 46
47 47 def test_index_grouped_by_date
48 48 get :index, :project_id => 'ecookbook', :sort_by => 'date'
49 49 assert_response :success
50 50 assert_tag 'h3', :content => '2007-02-12'
51 51 end
52 52
53 53 def test_index_grouped_by_title
54 54 get :index, :project_id => 'ecookbook', :sort_by => 'title'
55 55 assert_response :success
56 56 assert_tag 'h3', :content => 'T'
57 57 end
58 58
59 59 def test_index_grouped_by_author
60 60 get :index, :project_id => 'ecookbook', :sort_by => 'author'
61 61 assert_response :success
62 62 assert_tag 'h3', :content => 'John Smith'
63 63 end
64 64
65 65 def test_index_with_long_description
66 66 # adds a long description to the first document
67 67 doc = documents(:documents_001)
68 68 doc.update_attributes(:description => <<LOREM)
69 69 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut egestas, mi vehicula varius varius, ipsum massa fermentum orci, eget tristique ante sem vel mi. Nulla facilisi. Donec enim libero, luctus ac sagittis sit amet, vehicula sagittis magna. Duis ultrices molestie ante, eget scelerisque sem iaculis vitae. Etiam fermentum mauris vitae metus pharetra condimentum fermentum est pretium. Proin sollicitudin elementum quam quis pharetra. Aenean facilisis nunc quis elit volutpat mollis. Aenean eleifend varius euismod. Ut dolor est, congue eget dapibus eget, elementum eu odio. Integer et lectus neque, nec scelerisque nisi. EndOfLineHere
70 70
71 71 Vestibulum non velit mi. Aliquam scelerisque libero ut nulla fringilla a sollicitudin magna rhoncus. Praesent a nunc lorem, ac porttitor eros. Sed ac diam nec neque interdum adipiscing quis quis justo. Donec arcu nunc, fringilla eu dictum at, venenatis ac sem. Vestibulum quis elit urna, ac mattis sapien. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
72 72 LOREM
73 73
74 74 get :index, :project_id => 'ecookbook'
75 75 assert_response :success
76 76 assert_template 'index'
77 77
78 78 # should only truncate on new lines to avoid breaking wiki formatting
79 79 assert_select '.wiki p', :text => (doc.description.split("\n").first + '...')
80 80 assert_select '.wiki p', :text => Regexp.new(Regexp.escape("EndOfLineHere..."))
81 81 end
82 82
83 83 def test_show
84 84 get :show, :id => 1
85 85 assert_response :success
86 86 assert_template 'show'
87 87 end
88 88
89 def test_new_with_one_attachment
89 def test_new
90 @request.session[:user_id] = 2
91 get :new, :project_id => 1
92 assert_response :success
93 assert_template 'new'
94 end
95
96 def test_create_with_one_attachment
90 97 ActionMailer::Base.deliveries.clear
91 98 Setting.notified_events << 'document_added'
92 99 @request.session[:user_id] = 2
93 100 set_tmp_attachments_directory
94 101
95 post :new, :project_id => 'ecookbook',
102 post :create, :project_id => 'ecookbook',
96 103 :document => { :title => 'DocumentsControllerTest#test_post_new',
97 104 :description => 'This is a new document',
98 105 :category_id => 2},
99 106 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
100 107
101 108 assert_redirected_to '/projects/ecookbook/documents'
102 109
103 110 document = Document.find_by_title('DocumentsControllerTest#test_post_new')
104 111 assert_not_nil document
105 112 assert_equal Enumeration.find(2), document.category
106 113 assert_equal 1, document.attachments.size
107 114 assert_equal 'testfile.txt', document.attachments.first.filename
108 115 assert_equal 1, ActionMailer::Base.deliveries.size
109 116 end
110 117
111 118 def test_edit
112 119 @request.session[:user_id] = 2
113 120 get :edit, :id => 1
114 121 assert_response :success
115 122 assert_template 'edit'
116 123 end
117 124
118 125 def test_update
119 126 @request.session[:user_id] = 2
120 post :edit, :id => 1, :document => {:title => 'test_update'}
127 put :update, :id => 1, :document => {:title => 'test_update'}
121 128 assert_redirected_to '/documents/1'
122 129 document = Document.find(1)
123 130 assert_equal 'test_update', document.title
124 131 end
125 132
126 133 def test_destroy
127 134 @request.session[:user_id] = 2
128 135 assert_difference 'Document.count', -1 do
129 post :destroy, :id => 1
136 delete :destroy, :id => 1
130 137 end
131 138 assert_redirected_to '/projects/ecookbook/documents'
132 139 assert_nil Document.find_by_id(1)
133 140 end
134 141
135 142 def test_add_attachment
136 143 @request.session[:user_id] = 2
137 144 assert_difference 'Attachment.count' do
138 145 post :add_attachment, :id => 1,
139 146 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
140 147 end
141 148 attachment = Attachment.first(:order => 'id DESC')
142 149 assert_equal Document.find(1), attachment.container
143 150 end
144 151 end
General Comments 0
You need to be logged in to leave comments. Login now