第30回/フィルターで複数の親チケットを検索できるが、関連チケットも複数で検索できるようにしたい
関連Issue:
やること:
親チケットに対してのパッチが参考になるかも:
動作確認(ついでにDBテーブルチェック):
関連は種類が多い
一旦、"Related to"のみで絞って考えてみる
Fixturesデータ内には関連の初期設定データは含まれているが、親チケット(parent_id)が設定されたデータは含まれていない (issuesテーブルの"parent_id"カラム値より確認)
関連は"issue_relations"テーブルに保存されている
id issue_from_id issue_to_id relation_type
1 10 9 "blocks"
2 2 3 "relates"
3 2 15 "relates" <-- 動作確認時手動追加分
ちなみ関連種別は app/model/issue_relation.rb 内に下記のような形で存在
code:rb
TYPE_RELATES = "relates"
TYPE_DUPLICATES = "duplicates"
TYPE_DUPLICATED = "duplicated"
TYPE_BLOCKS = "blocks"
TYPE_BLOCKED = "blocked"
TYPE_PRECEDES = "precedes"
TYPE_FOLLOWS = "follows"
TYPE_COPIED_TO = "copied_to"
TYPE_COPIED_FROM = "copied_from"
パッチ案検討
app/model/issue_query.rb 内に sql_for_parent_id_field(field, operator, value)と同様に sql_for_relations(field, operator, value, options={}) 関数があるので、ここでカンマ区切りを取れないか検討してみる
上記関数の戻り値sqlのWHERE句は以下のようになる
code:sql
issues.id IN (
SELECT DISTINCT issue_relations.issue_to_id
FROM issue_relations
WHERE issue_relations.relation_type = 'relates'
AND issue_relations.issue_from_id = 2
)
なお、"Related to"に関しては、本来は片方向だけでなく、双方向を見ないといけない。
(が、SQL分岐が少し複雑になりそうなので、もう少し後で検討します)
まずは、valueには ["2,3"] のようなカンマ区切りの値が入ってきているので、こちらを利用できないか検討する。
issue_relations.issue_from_id = 2 は issue_relations.issue_from_id IN (2) としてみる。
SQLエラー発生
code:sql
SELECT COUNT(*) FROM "issues"
INNER JOIN "projects" ON "projects"."id" = "issues"."project_id"
INNER JOIN "issue_statuses" ON "issue_statuses"."id" = "issues"."status_id"
WHERE (projects.status <> 9 AND projects.status <> 10 AND EXISTS (
SELECT 1 AS one FROM enabled_modules em WHERE em.project_id = projects.id AND em.name='issue_tracking'
) -- EXISTS
) -- projects.status
AND (
(issues.status_id IN (SELECT id FROM issue_statuses WHERE is_closed=FALSE)) AND
(issues.id IN (SELECT DISTINCT issue_relations.issue_from_id
FROM issue_relations WHERE issue_relations.relation_type = 'relates'
AND issue_relations.issue_to_id IN (3,2))
OR
(issues.id IN (SELECT DISTINCT issue_relations.issue_to_id
FROM issue_relations WHERE issue_relations.relation_type = 'relates'
AND issue_relations.issue_from_id IN (3,2))
)) AND projects.lft >= 1 AND projects.rgt <= 10)
閉じカッコが抜けてたことが原因でした...。閉じカッコ追加後、SQLも流れることを確認
こちらの差分で、それらしき結果が出ることを確認。
code:diff
--- a/app/models/issue_query.rb
+++ b/app/models/issue_query.rb
@@ -723,6 +723,7 @@ class IssueQuery < Query
relation_type = relation_options:reverse || relation_type join_column, target_join_column = target_join_column, join_column
end
+ ids = value.first.to_s.scan(/\d+/).map(&:to_i).uniq
sql =
case operator
when "*", "!*"
@@ -739,7 +740,7 @@ class IssueQuery < Query
" '#{self.class.connection.quote_string(relation_type)}'" \
テストの追加
まず、現状のquery_testに影響ないか確認 rails test test/unit/query_test.rb
OK
test/unit/query_test.rb の test_filter_on_relations_with_a_specific_issue 内で、以下の追加の関連が設定されている
id issue_from_id issue_to_id relation_type
1 10 9 "blocks"
2 2 3 "relates"
3 1 2 "relates"
4 3 1 "relates"
code:rb
query = IssueQuery.new(:name => '_')
query.filters = {"relates" => {:operator => '=', :values => '1,2'}} assert_equal 1, 2, 3, find_issues_with_query(query).map(&:id).sort :
rails test test/unit/query_test.rb:1327
テストが通ることを確認
本家パッチ投稿
門屋さんの親チケットのを参考にする