# Reverses the relation if needed so that it gets stored in the proper way
# Should not be reversed before validation so that it can be displayed back
- # as entered on new relation form
+ # as entered on new relation form.
+ #
+ # Orders relates relations by ID, so that uniqueness index in DB is triggered
+ # on concurrent access.
def reverse_if_needed
if TYPES.has_key?(relation_type) && TYPES[relation_type][:reverse]
issue_tmp = issue_to
self.issue_to = issue_from
self.issue_from = issue_tmp
self.relation_type = TYPES[relation_type][:reverse]
+
+ elsif relation_type == TYPE_RELATES && issue_from_id > issue_to_id
+ self.issue_to, self.issue_from = issue_from, issue_to
end
end
issue_from.blocks? issue_to
when 'blocks'
issue_to.blocks? issue_from
+ when 'relates'
+ self.class.where(issue_from_id: issue_to, issue_to_id: issue_from).present?
else
false
end
assert_equal 'text/javascript', response.content_type
end
relation = IssueRelation.order('id DESC').first
- assert_equal 3, relation.issue_from_id
- assert_equal 1, relation.issue_to_id
+ assert_equal 1, relation.issue_from_id
+ assert_equal 3, relation.issue_to_id
assert_include 'Bug #1', response.body
end
assert_equal from, relation.issue_to
end
+ def test_cannot_create_inverse_relates_relations
+ from = Issue.find(1)
+ to = Issue.find(2)
+
+ relation1 = IssueRelation.new :issue_from => from, :issue_to => to,
+ :relation_type => IssueRelation::TYPE_RELATES
+ assert relation1.save
+
+ relation2 = IssueRelation.new :issue_from => to, :issue_to => from,
+ :relation_type => IssueRelation::TYPE_RELATES
+ assert !relation2.save
+ assert_not_equal [], relation2.errors[:base]
+ end
+
def test_follows_relation_should_not_be_reversed_if_validation_fails
from = Issue.find(1)
to = Issue.find(2)