Feature #41214 » allow-OR-logical-operatori-in-query.patch
app/models/query.rb | ||
---|---|---|
259 | 259 |
VISIBILITY_PRIVATE = 0 |
260 | 260 |
VISIBILITY_ROLES = 1 |
261 | 261 |
VISIBILITY_PUBLIC = 2 |
262 |
FILTER_CONNECTION_AND = 'AND' |
|
263 |
FILTER_CONNECTION_OR = 'OR' |
|
264 |
FILTER_CONNECTIONS = [FILTER_CONNECTION_AND, FILTER_CONNECTION_OR] |
|
262 | 265 | |
263 | 266 |
belongs_to :project |
264 | 267 |
belongs_to :user |
... | ... | |
455 | 458 |
end |
456 | 459 | |
457 | 460 |
query_params = params[:query] || defaults || {} |
461 |
self.filter_connection = query_params[:filter_connection] || self.filter_connection |
|
458 | 462 |
self.group_by = params[:group_by] || query_params[:group_by] || self.group_by |
459 | 463 |
self.column_names = params[:c] || query_params[:column_names] || self.column_names |
460 | 464 |
self.totalable_names = params[:t] || query_params[:totalable_names] || self.totalable_names |
... | ... | |
1029 | 1033 |
end |
1030 | 1034 |
end if filters and valid? |
1031 | 1035 | |
1036 |
filters_clauses.reject!(&:blank?) |
|
1037 |
filters_clauses = filters_clauses.any? ? [filters_clauses.join(" #{filter_connection} ")] : [] |
|
1038 | ||
1032 | 1039 |
if (c = group_by_column) && c.is_a?(QueryCustomFieldColumn) |
1033 | 1040 |
# Excludes results for which the grouped custom field is not visible |
1034 | 1041 |
filters_clauses << c.custom_field.visibility_by_project_condition |
... | ... | |
1080 | 1087 |
end |
1081 | 1088 |
end |
1082 | 1089 | |
1090 |
def filter_connection |
|
1091 |
if FILTER_CONNECTIONS.include?(options[:filter_connection].to_s) |
|
1092 |
options[:filter_connection] |
|
1093 |
else |
|
1094 |
FILTER_CONNECTION_AND |
|
1095 |
end |
|
1096 |
end |
|
1097 | ||
1098 |
def filter_connection=(connection) |
|
1099 |
if FILTER_CONNECTIONS.include?(connection) |
|
1100 |
options[:filter_connection] = connection |
|
1101 |
else |
|
1102 |
options.delete(:filter_connection) |
|
1103 |
end |
|
1104 |
end |
|
1105 | ||
1083 | 1106 |
def display_type |
1084 | 1107 |
options[:display_type] || self.default_display_type |
1085 | 1108 |
end |
app/views/queries/_filters.html.erb | ||
---|---|---|
15 | 15 |
<% end %> |
16 | 16 | |
17 | 17 |
<div id="filters-table"> |
18 |
<div class="filter"> |
|
19 |
<div class="field"><label for='filter_connection'><%= l(:field_filter_connection) %></label></div> |
|
20 |
<%= hidden_field_tag 'selected_filter_connection', @query.filter_connection %> |
|
21 |
<%= select_tag 'query[filter_connection]', options_for_select(Query::FILTER_CONNECTIONS.map{|c| [l("label_filter_connection_#{c.downcase}"), c]}, @query.filter_connection) %> |
|
22 |
</div> |
|
18 | 23 |
</div> |
19 | 24 | |
20 | 25 |
<div class="add-filter"> |
config/locales/en.yml | ||
---|---|---|
791 | 791 |
label_filter_plural: Filters |
792 | 792 |
label_equals: is |
793 | 793 |
label_not_equals: is not |
794 |
field_filter_connection: Filter Connection |
|
795 |
label_filter_connection_and: (AND) Match all filters |
|
796 |
label_filter_connection_or: (OR) Match any filter |
|
794 | 797 |
label_in_less_than: in less than |
795 | 798 |
label_in_more_than: in more than |
796 | 799 |
label_in_the_next_days: in the next |
config/locales/ja.yml | ||
---|---|---|
625 | 625 |
label_filter_plural: フィルタ |
626 | 626 |
label_equals: 等しい |
627 | 627 |
label_not_equals: 等しくない |
628 |
field_filter_connection: フィルタの接続条件 |
|
629 |
label_filter_connection_and: (AND) すべてのフィルタに一致 |
|
630 |
label_filter_connection_or: (OR) いずれかのフィルタに一致 |
|
628 | 631 |
label_in_less_than: N日後以前 |
629 | 632 |
label_in_more_than: N日後以降 |
630 | 633 |
label_greater_or_equal: 以上 |
test/functional/issues_controller_test.rb | ||
---|---|---|
344 | 344 |
assert_not_include 4, issues |
345 | 345 |
end |
346 | 346 | |
347 |
def test_index_with_filters_using_filter_connection_and |
|
348 |
Issue.destroy_all |
|
349 |
issues_filterd = [ |
|
350 |
Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'Issue created by user 2 and assigned_to user 2', :author_id => 2, :assigned_to_id => 2) |
|
351 |
] |
|
352 |
issues_not_filtered = [ |
|
353 |
Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'Issue created by user 2', :author_id => 2, :assigned_to_id => nil), |
|
354 |
Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'issue assisgned to user 2', :author_id => 3, :assigned_to_id => 2) |
|
355 |
] |
|
356 | ||
357 |
get( |
|
358 |
:index, |
|
359 |
:params => { |
|
360 |
:project_id => 1, |
|
361 |
:set_filter => 1, |
|
362 |
:query => { :filter_connection => 'AND', }, |
|
363 |
:f => ['author_id', 'assigned_to_id'], |
|
364 |
:op => { 'author_id' => '=', 'assigned_to_id' => '=' }, |
|
365 |
:v => { 'author_id' => ['2'], 'assigned_to_id' => ['2'] } |
|
366 |
} |
|
367 |
) |
|
368 |
assert_response :success |
|
369 | ||
370 |
issues = issues_in_list.map(&:id).uniq.sort |
|
371 |
issues_filterd.each do |issue| |
|
372 |
assert_include issue.id, issues |
|
373 |
end |
|
374 |
issues_not_filtered.each do |issue| |
|
375 |
assert_not_include issue.id, issues |
|
376 |
end |
|
377 |
end |
|
378 | ||
379 |
def test_index_with_filters_using_filter_connection_or |
|
380 |
Issue.destroy_all |
|
381 |
issues_filterd = [ |
|
382 |
Issue.create!(:project_id => 1, :tracker_id => 1, |
|
383 |
:subject => 'Issue created by user 2', |
|
384 |
:author_id => 2, :assigned_to_id => nil), |
|
385 |
Issue.create!(:project_id => 1, :tracker_id => 1, |
|
386 |
:subject => 'issue assisgned to user 2', |
|
387 |
:author_id => 3, :assigned_to_id => 2) |
|
388 |
] |
|
389 |
issues_not_filtered = [ |
|
390 |
Issue.create!(:project_id => 1, :tracker_id => 1, |
|
391 |
:subject => 'Issue created by user 3', |
|
392 |
:author_id => 3, :assigned_to_id => nil) |
|
393 |
] |
|
394 | ||
395 |
get( |
|
396 |
:index, |
|
397 |
:params => { |
|
398 |
:project_id => 1, |
|
399 |
:set_filter => 1, |
|
400 |
:query => { :filter_connection => 'OR' }, |
|
401 |
:f => ['author_id', 'assigned_to_id'], |
|
402 |
:op => { 'author_id' => '=', 'assigned_to_id' => '=' }, |
|
403 |
:v => { 'author_id' => ['2'], 'assigned_to_id' => ['2'] } |
|
404 |
} |
|
405 |
) |
|
406 |
assert_response :success |
|
407 | ||
408 |
issues = issues_in_list.map(&:id).uniq.sort |
|
409 |
issues_filterd.each do |issue| |
|
410 |
assert_include issue.id, issues |
|
411 |
end |
|
412 |
issues_not_filtered.each do |issue| |
|
413 |
assert_not_include issue.id, issues |
|
414 |
end |
|
415 |
end |
|
416 | ||
347 | 417 |
def test_index_with_query |
348 | 418 |
get( |
349 | 419 |
:index, |
test/unit/query_test.rb | ||
---|---|---|
2031 | 2031 |
assert_nil q.statement |
2032 | 2032 |
end |
2033 | 2033 | |
2034 |
def test_statement_should_connect_filters_with_and_when_filter_connection_is_blank |
|
2035 |
q = IssueQuery.new(:name => '_') |
|
2036 |
q.filters = { |
|
2037 |
'status_id' => {:operator => '=', :values => ['1']}, |
|
2038 |
'priority_id' => {:operator => '=', :values => ['4']} |
|
2039 |
} |
|
2040 | ||
2041 |
assert q.valid? |
|
2042 |
assert_equal "(issues.status_id IN ('1')) AND (issues.priority_id IN ('4'))", q.statement |
|
2043 |
end |
|
2044 | ||
2045 |
def test_statument_should_connect_filters_with_and_when_filter_connection_is_and |
|
2046 |
q = IssueQuery.new(:name => '_', :filter_connection => 'AND') |
|
2047 |
q.filters = { |
|
2048 |
'status_id' => {:operator => '=', :values => ['1']}, |
|
2049 |
'priority_id' => {:operator => '=', :values => ['4']} |
|
2050 |
} |
|
2051 | ||
2052 |
assert q.valid? |
|
2053 |
assert_equal "(issues.status_id IN ('1')) AND (issues.priority_id IN ('4'))", q.statement |
|
2054 |
end |
|
2055 | ||
2056 |
def test_statement_should_be_changed_connected_with_or_when_filter_connection_is_or |
|
2057 |
q = IssueQuery.new(:name => '_', :filter_connection => 'OR') |
|
2058 |
q.filters = { |
|
2059 |
'status_id' => {:operator => '=', :values => ['1']}, |
|
2060 |
'priority_id' => {:operator => '=', :values => ['4']} |
|
2061 |
} |
|
2062 | ||
2063 |
assert q.valid? |
|
2064 |
assert_equal "(issues.status_id IN ('1')) OR (issues.priority_id IN ('4'))", q.statement |
|
2065 |
end |
|
2066 | ||
2034 | 2067 |
def test_available_filters_as_json_should_include_missing_assigned_to_id_values |
2035 | 2068 |
user = User.generate! |
2036 | 2069 |
with_current_user User.find(1) do |
... | ... | |
3391 | 3424 |
end |
3392 | 3425 |
end |
3393 | 3426 | |
3427 |
def test_filter_connection_should_accept_known_values |
|
3428 |
query = IssueQuery.new(:name => '_') |
|
3429 |
query.filter_connection = 'AND' |
|
3430 |
assert_equal 'AND', query.filter_connection |
|
3431 |
query.filter_connection = 'OR' |
|
3432 |
assert_equal 'OR', query.filter_connection |
|
3433 |
end |
|
3434 | ||
3435 |
def test_filter_connection_should_not_accept_unknown_values |
|
3436 |
query = IssueQuery.new(:name => '_') |
|
3437 |
query.filter_connection = 'invalid' |
|
3438 |
assert_equal 'AND', query.filter_connection |
|
3439 |
end |
|
3440 | ||
3394 | 3441 |
def test_display_type_should_accept_known_types |
3395 | 3442 |
query = ProjectQuery.new(:name => '_') |
3396 | 3443 |
query.display_type = 'list' |
- « Previous
- 1
- 2
- Next »