diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index c8778b473..1bf969cd5 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -90,7 +90,9 @@ class IssuesController < ApplicationController respond_to do |format| format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? } - format.api + format.api { + Issue.load_relations(@issues) if include_in_api_response?('relations') + } format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") } format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') } format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') } diff --git a/app/models/issue.rb b/app/models/issue.rb index 48a0afb2a..ccd326552 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -508,7 +508,17 @@ class Issue < ActiveRecord::Base end def relations - (relations_from + relations_to).sort + @relations ||= (relations_from + relations_to).sort + end + + # Preloads relations for a collection of issues + def self.load_relations(issues) + if issues.any? + relations = IssueRelation.all(:conditions => ["issue_from_id IN (:ids) OR issue_to_id IN (:ids)", {:ids => issues.map(&:id)}]) + issues.each do |issue| + issue.instance_variable_set "@relations", relations.select {|r| r.issue_from_id == issue.id || r.issue_to_id == issue.id} + end + end end # Finds an issue relation given its id. diff --git a/app/views/issues/index.api.rsb b/app/views/issues/index.api.rsb index 1ec2acc10..2c09df41b 100644 --- a/app/views/issues/index.api.rsb +++ b/app/views/issues/index.api.rsb @@ -23,6 +23,12 @@ api.array :issues, api_meta(:total_count => @issue_count, :offset => @offset, :l api.created_on issue.created_on api.updated_on issue.updated_on + + api.array :relations do + issue.relations.each do |relation| + api.relation(:id => relation.id, :issue_id => relation.issue_from_id, :issue_to_id => relation.issue_to_id, :relation_type => relation.relation_type, :delay => relation.delay) + end + end if include_in_api_response?('relations') end end end diff --git a/test/integration/api_test/issues_test.rb b/test/integration/api_test/issues_test.rb index 3dbd229a2..117dde1b1 100644 --- a/test/integration/api_test/issues_test.rb +++ b/test/integration/api_test/issues_test.rb @@ -47,7 +47,7 @@ class ApiTest::IssuesTest < ActionController::IntegrationTest Setting.rest_api_enabled = '1' end - context "/index.xml" do + context "/issues" do # Use a private project to make sure auth is really working and not just # only showing public issues. should_allow_api_authentication(:get, "/projects/private-child/issues.xml") @@ -102,6 +102,25 @@ class ApiTest::IssuesTest < ActionController::IntegrationTest end end + context "with relations" do + should "display relations" do + get '/issues.xml?include=relations' + + assert_response :success + assert_equal 'application/xml', @response.content_type + assert_tag 'relations', + :parent => {:tag => 'issue', :child => {:tag => 'id', :content => '3'}}, + :children => {:count => 1}, + :child => { + :tag => 'relation', + :attributes => {:id => '2', :issue_id => '2', :issue_to_id => '3', :relation_type => 'relates'} + } + assert_tag 'relations', + :parent => {:tag => 'issue', :child => {:tag => 'id', :content => '1'}}, + :children => {:count => 0} + end + end + context "with invalid query params" do should "return errors" do get '/issues.xml', {:f => ['start_date'], :op => {:start_date => '='}}