Index: app/controllers/issue_relations_controller.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- app/controllers/issue_relations_controller.rb (revision ad37098676177d2e30dae0dcc7575b0c93769274) +++ app/controllers/issue_relations_controller.rb (revision 27923fae6ba1509f770a95a3609c01f73288732b) @@ -44,16 +44,24 @@ end def create - @relation = IssueRelation.new - @relation.issue_from = @issue - @relation.safe_attributes = params[:relation] - @relation.init_journals(User.current) + saved = nil + bulk_relations ||= [] + + relation_issues_to_id.each do |issue_to_id| + @relation = IssueRelation.new + @relation.issue_from = @issue + @relation.safe_attributes = params[:relation] + @relation.issue_to = Issue.visible(User.current).find_by_id(issue_to_id.delete('^0-9')) + @relation.init_journals(User.current) - begin - saved = @relation.save - rescue ActiveRecord::RecordNotUnique - saved = false - @relation.errors.add :base, :taken + begin + saved = @relation.save + rescue ActiveRecord::RecordNotUnique + saved = false + @relation.errors.add :base, :taken + end + bulk_relations << @relation + @relation_errors = bulk_relations.map {|o| o.errors.full_messages}.flatten end respond_to do |format| @@ -97,4 +105,15 @@ rescue ActiveRecord::RecordNotFound render_404 end + + def relation_issues_to_id + issue_to_id = params[:relation].require(:issue_to_id) + issue_to_id = issue_to_id.scan(/#?[0-9]+,?/) + raise Unauthorized if issue_to_id.size.zero? + + issue_to_id + rescue ActionController::ParameterMissing => e + render_error(:message => e.message, :status => 400) + [] + end end Index: app/models/issue_relation.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- app/models/issue_relation.rb (revision ad37098676177d2e30dae0dcc7575b0c93769274) +++ app/models/issue_relation.rb (revision 27923fae6ba1509f770a95a3609c01f73288732b) @@ -89,15 +89,8 @@ end return unless attrs.is_a?(Hash) + attrs = attrs.deep_dup - - if issue_id = attrs.delete('issue_to_id') - if issue_id.to_s.strip.match(/\A#?(\d+)\z/) - issue_id = $1.to_i - self.issue_to = Issue.visible(user).find_by_id(issue_id) - end - end - super(attrs) end Index: app/views/issue_relations/_form.html.erb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- app/views/issue_relations/_form.html.erb (revision ad37098676177d2e30dae0dcc7575b0c93769274) +++ app/views/issue_relations/_form.html.erb (revision 27923fae6ba1509f770a95a3609c01f73288732b) @@ -1,4 +1,4 @@ -<%= error_messages_for 'relation' %> +<%= render_error_messages(@relation_errors) if @relation_errors %>

<%= f.select :relation_type, collection_for_relation_type_select, {}, :onchange => "setPredecessorFieldsVisibility();" %> <%= l(:label_issue) %> #<%= f.text_field :issue_to_id, :size => 10 %> Index: test/functional/issue_relations_controller_test.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- test/functional/issue_relations_controller_test.rb (revision ad37098676177d2e30dae0dcc7575b0c93769274) +++ test/functional/issue_relations_controller_test.rb (revision 27923fae6ba1509f770a95a3609c01f73288732b) @@ -55,6 +55,43 @@ assert_equal 'relates', relation.relation_type end + def test_bulk_create + assert_difference 'IssueRelation.count', +3 do + post :create, :params => { + :issue_id => 1, + :relation => { + :issue_to_id => '2,3,7', + :relation_type => 'relates', + :delay => '' + } + } + end + relations = IssueRelation.where(:issue_from_id => 1, :issue_to_id => [2,3,7]) + assert_equal 3, relations.count + # all relations types should be 'relates' + relations.map { |r| assert_equal 'relates', r.relation_type } + end + + def test_bulk_create_should_show_errors + assert_difference 'IssueRelation.count', +3 do + post :create, :params => { + :issue_id => 1, + :relation => { + :issue_to_id => '2,3,4,5,7', + :relation_type => 'relates', + :delay => '' + } + }, + :xhr => true + end + assert_response :success + assert_equal 'text/javascript', response.media_type + + # issues #4 and #5 can't be related by default + assert_include 'Related issue cannot be blank', response.body + assert_include 'Related issue doesn't belong to the same project', response.body + end + def test_create_on_invalid_issue assert_no_difference 'IssueRelation.count' do post :create, :params => {