Feature #31472 » 31472-add-file-upload.patch
| app/controllers/documents_controller.rb | ||
|---|---|---|
| 75 | 75 |
@document.safe_attributes = params[:document] |
| 76 | 76 |
if @document.save |
| 77 | 77 |
flash[:notice] = l(:notice_successful_update) |
| 78 |
redirect_to document_path(@document)
|
|
| 78 |
add_attachment
|
|
| 79 | 79 |
else |
| 80 | 80 |
render :action => 'edit' |
| 81 | 81 |
end |
| app/models/document.rb | ||
|---|---|---|
| 31 | 31 |
:url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
|
| 32 | 32 |
acts_as_activity_provider :scope => preload(:project) |
| 33 | 33 | |
| 34 |
attr_writer :deleted_attachment_ids |
|
| 35 | ||
| 34 | 36 |
validates_presence_of :project, :title, :category |
| 35 | 37 |
validates_length_of :title, :maximum => 255 |
| 36 | 38 | |
| 39 |
after_save :delete_selected_attachments |
|
| 37 | 40 |
after_create_commit :send_notification |
| 38 | 41 | |
| 39 | 42 |
scope :visible, lambda {|*args|
|
| ... | ... | |
| 42 | 45 |
} |
| 43 | 46 | |
| 44 | 47 |
safe_attributes 'category_id', 'title', 'description', 'custom_fields', 'custom_field_values' |
| 48 |
safe_attributes( |
|
| 49 |
'deleted_attachment_ids', |
|
| 50 |
:if => lambda {|document, user| document.attachments_deletable?(user)}
|
|
| 51 |
) |
|
| 45 | 52 | |
| 46 | 53 |
def visible?(user=User.current) |
| 47 | 54 |
!user.nil? && user.allowed_to?(:view_documents, project) |
| ... | ... | |
| 66 | 73 |
project.notified_users.reject {|user| !visible?(user)}
|
| 67 | 74 |
end |
| 68 | 75 | |
| 76 |
def deleted_attachment_ids |
|
| 77 |
Array(@deleted_attachment_ids).map(&:to_i) |
|
| 78 |
end |
|
| 79 | ||
| 69 | 80 |
private |
| 70 | 81 | |
| 82 |
def delete_selected_attachments |
|
| 83 |
deleted_ids = deleted_attachment_ids |
|
| 84 |
return if deleted_ids.blank? |
|
| 85 |
objects = attachments.where(:id => deleted_ids) |
|
| 86 |
attachments.delete(objects) if objects.exists? |
|
| 87 |
end |
|
| 88 | ||
| 71 | 89 |
def send_notification |
| 72 | 90 |
if Setting.notified_events.include?('document_added')
|
| 73 | 91 |
Mailer.deliver_document_added(self, User.current) |
| app/views/documents/_form.html.erb | ||
|---|---|---|
| 13 | 13 |
<% @document.custom_field_values.each do |value| %> |
| 14 | 14 |
<p><%= custom_field_tag_with_label :document, value %></p> |
| 15 | 15 |
<% end %> |
| 16 |
</div> |
|
| 17 | 16 | |
| 18 | 17 |
<%= wikitoolbar_for 'document_description' %> |
| 19 | 18 | |
| 20 |
<% if @document.new_record? %> |
|
| 21 |
<div class="box tabular"> |
|
| 22 |
<p><label><%=l(:label_attachment_plural)%></label><%= render :partial => 'attachments/form', :locals => {:container => @document} %></p>
|
|
| 19 |
<fieldset> |
|
| 20 |
<legend><%=l(:label_attachment_plural)%></legend> |
|
| 21 |
<% if @document.attachments.any? && @document.safe_attribute?('deleted_attachment_ids') %>
|
|
| 22 |
<div class="contextual"><%= link_to l(:label_edit_attachments), '#', :onclick => "$('#existing-attachments').toggle(); return false;" %></div>
|
|
| 23 |
<div id="existing-attachments" style="<%= 'display:none;' if @document.deleted_attachment_ids.blank? %>"> |
|
| 24 |
<% @document.attachments.each do |attachment| %> |
|
| 25 |
<span class="existing-attachment"> |
|
| 26 |
<%= text_field_tag '', attachment.filename, :class => "icon icon-attachment filename", :disabled => true %> |
|
| 27 |
<label class='inline'> |
|
| 28 |
<%= check_box_tag 'document[deleted_attachment_ids][]', |
|
| 29 |
attachment.id, |
|
| 30 |
@document.deleted_attachment_ids.include?(attachment.id), |
|
| 31 |
:id => nil, :class => "deleted_attachment" %> <%= l(:button_delete) %> |
|
| 32 |
</label> |
|
| 33 |
</span> |
|
| 34 |
<% end %> |
|
| 35 |
<hr /> |
|
| 23 | 36 |
</div> |
| 24 | 37 |
<% end %> |
| 38 |
<div id="new-attachments" style="display:inline-block;"> |
|
| 39 |
<%= render :partial => 'attachments/form', :locals => {:container => @document} %>
|
|
| 40 |
</div> |
|
| 41 |
</fieldset> |
|
| 42 |
</div> |
|
| test/functional/documents_controller_test.rb | ||
|---|---|---|
| 207 | 207 |
end |
| 208 | 208 | |
| 209 | 209 |
def test_update |
| 210 |
set_tmp_attachments_directory |
|
| 210 | 211 |
@request.session[:user_id] = 2 |
| 211 |
put :update, :params => {
|
|
| 212 |
:id => 1, |
|
| 213 |
:document => {
|
|
| 214 |
:title => 'test_update' |
|
| 212 |
assert_difference 'Attachment.count' do |
|
| 213 |
put :update, :params => {
|
|
| 214 |
:id => 1, |
|
| 215 |
:document => {
|
|
| 216 |
:title => 'test_update' |
|
| 217 |
}, |
|
| 218 |
:attachments => {
|
|
| 219 |
'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}
|
|
| 220 |
} |
|
| 215 | 221 |
} |
| 216 |
}
|
|
| 222 |
end
|
|
| 217 | 223 |
assert_redirected_to '/documents/1' |
| 218 | 224 |
document = Document.find(1) |
| 219 | 225 |
assert_equal 'test_update', document.title |
| 220 | 226 |
end |
| 221 | 227 | |
| 222 | 228 |
def test_update_with_failure |
| 229 |
set_tmp_attachments_directory |
|
| 230 |
@request.session[:user_id] = 2 |
|
| 231 |
assert_no_difference 'Attachment.count' do |
|
| 232 |
put :update, :params => {
|
|
| 233 |
:id => 1, |
|
| 234 |
:document => {
|
|
| 235 |
:title => '' |
|
| 236 |
}, |
|
| 237 |
:attachments => {
|
|
| 238 |
'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}
|
|
| 239 |
} |
|
| 240 |
} |
|
| 241 |
end |
|
| 242 |
assert_response :success |
|
| 243 |
assert_select_error /title cannot be blank/i |
|
| 244 |
end |
|
| 245 | ||
| 246 |
def test_update_with_deleted_attachment_ids |
|
| 247 |
set_tmp_attachments_directory |
|
| 223 | 248 |
@request.session[:user_id] = 2 |
| 224 |
put :update, :params => {
|
|
| 249 |
document = Document.find(1) |
|
| 250 |
attachment = document.attachments.first |
|
| 251 |
assert_difference 'Attachment.count', -1 do |
|
| 252 |
put :update, :params => {
|
|
| 225 | 253 |
:id => 1, |
| 226 | 254 |
:document => {
|
| 227 |
:title => '' |
|
| 255 |
:title => 'test_update', |
|
| 256 |
:deleted_attachment_ids => [attachment.id] |
|
| 228 | 257 |
} |
| 229 | 258 |
} |
| 230 |
assert_response :success |
|
| 231 |
assert_select_error /title cannot be blank/i |
|
| 259 |
end |
|
| 260 |
document.reload |
|
| 261 |
refute_includes document.attachments, attachment |
|
| 262 |
end |
|
| 263 | ||
| 264 |
def test_update_with_deleted_attachment_ids_and_failure_should_preserve_selected_attachments |
|
| 265 |
set_tmp_attachments_directory |
|
| 266 |
@request.session[:user_id] = 2 |
|
| 267 |
document = Document.find(1) |
|
| 268 |
attachment = document.attachments.first |
|
| 269 |
assert_no_difference 'Attachment.count' do |
|
| 270 |
put :update, :params => {
|
|
| 271 |
:id => 1, |
|
| 272 |
:document => {
|
|
| 273 |
:title => '', |
|
| 274 |
:deleted_attachment_ids => [attachment.id] |
|
| 275 |
} |
|
| 276 |
} |
|
| 277 |
end |
|
| 278 |
document.reload |
|
| 279 |
assert_includes document.attachments, attachment |
|
| 232 | 280 |
end |
| 233 | 281 | |
| 234 | 282 |
def test_destroy |