-
Notifications
You must be signed in to change notification settings - Fork 1k
Fixes #38024 - Add ordering by virtual columns #10381
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes #38024 - Add ordering by virtual columns #10381
Conversation
|
It seems to work as expected in ui and api, the code makes sense but I think we need a Ruby person to verify it, @adamruzicka ? |
adamruzicka
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks reasonable, left two comments. Could we also get a related patch in one of the plugins where its needed?
| if virt_column.blank? || model_of_controller.columns_hash[virt_column] || !base_scope.respond_to?(select_method) | ||
| base_scope.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page], :per_page => params[:per_page]) | ||
| else | ||
| base_scope.send(select_method).search_for(params[:search]).order(params[:order]).paginate(:page => params[:page], :per_page => params[:per_page]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UI does not accept per_page being set to all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, thinking out loud, from the name I wouldn't really expect it to deal with pagination and so on, but that might be just me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UI does not accept per_page being set to all?
Nope, otherwise we'd have a button suggesting that.
Also, thinking out loud, from the name I wouldn't really expect it to deal with pagination and so on, but that might be just me
Naming is hard, any suggestion is more than welcome 🍪
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this break per_page=all for api?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this break per_page=all for api?
wrap_for_virt_column_select method is only for UI controllers, thus no.
API controllers most (if not all) of the time use resource_scope_for_index method, which is overridden in this PR:
https://github.com/theforeman/foreman/pull/10381/files#diff-f97adc72a387ed049f1b789f93f9d5c592f481e9e37c6fb75eabfcc2f36d467eR172
This override should not affect per_page=all, since it's either uses super to use old behavior or explicitly deals with it in https://github.com/theforeman/foreman/pull/10381/files#diff-f97adc72a387ed049f1b789f93f9d5c592f481e9e37c6fb75eabfcc2f36d467eR181.
56d9b7a to
373036f
Compare
373036f to
0039511
Compare
|
I've updated the logic a bit: since most of the UI controllers use WDYT? Should we expose the wrapper or rather force usage of already defined loaders if ordering by virt columns desired? |
0039511 to
4fea540
Compare
4fea540 to
dfc8198
Compare
dfc8198 to
b0ae94f
Compare
|
@adamruzicka, @MariaAga, reviving this one: do we still want that? Note: it also fixes broken ordering by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds the ability to order by virtual columns in Foreman, specifically enabling ordering by the "locked" column in the roles model. This addresses issue #38024 by allowing users to sort roles by their locked status both in the UI and API.
- Implements virtual column ordering support in both UI and API controllers
- Adds a
select_lockedscope to the Role model to define the virtual "locked" column - Updates roles controller to use the new ordering functionality
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| app/models/role.rb | Adds select_locked scope to define the virtual locked column |
| app/controllers/roles_controller.rb | Updates to use resource_base_search_and_page for virtual column support |
| app/controllers/application_controller.rb | Implements core virtual column ordering logic in resource_base_with_search |
| app/controllers/api/v2/base_controller.rb | Adds virtual column ordering support to API controllers |
| test/controllers/roles_controller_test.rb | Adds test for UI ordering by locked column |
| test/controllers/api/v2/roles_controller_test.rb | Adds comprehensive tests for API ordering by locked column |
| developer_docs/how_to_create_a_plugin.asciidoc | Documents how to implement virtual column ordering in plugins |
| select_method = "select_#{virt_column}" | ||
| if virt_column.blank? || model_of_controller.columns_hash[virt_column] || !resource_base.respond_to?(select_method) | ||
| resource_base.search_for(params[:search], :order => params[:order]) | ||
| else |
Copilot
AI
Jul 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using send with user-controlled input (select_method derived from params[:order]) could be a security risk. Consider using a whitelist approach or validating the method name against allowed virtual columns.
| select_method = "select_#{virt_column}" | |
| if virt_column.blank? || model_of_controller.columns_hash[virt_column] || !resource_base.respond_to?(select_method) | |
| resource_base.search_for(params[:search], :order => params[:order]) | |
| else | |
| allowed_virtual_columns = %w[column1 column2 column3] # Replace with actual allowed column names | |
| if virt_column.blank? || model_of_controller.columns_hash[virt_column] || !allowed_virtual_columns.include?(virt_column) | |
| resource_base.search_for(params[:search], :order => params[:order]) | |
| else | |
| select_method = "select_#{virt_column}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applied as 3776040.
b0ae94f to
b548dc4
Compare
| virt_column = extract_virtual_column | ||
| select_method = "select_#{virt_column}" | ||
| scope = resource_scope(...) | ||
|
|
||
| if virt_column.blank? || resource_class.columns_hash[virt_column] || !scope.virtual_column_scopes.include?(select_method.to_sym) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have this pattern with small differences in three different places, could we make it dryer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. It indeed looks better now.
3187f17 to
c6ff412
Compare
c6ff412 to
a5c1ede
Compare
|
/packit build |
a5c1ede to
85e3145
Compare
| model = respond_to?(:model_of_controller) ? model_of_controller : resource_class | ||
| return if virt_column.blank? || model.columns_hash[virt_column] || !base_scope.virtual_column_scopes.include?(select_method.to_sym) | ||
| base_scope.public_send(select_method).search_for(params[:search]).order(params[:order]) | ||
| base_scope.public_send(select_method).search_for(params[:search]).reorder(params[:order]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This already considers unless params[:order].blank? since if it's empty the method returns earlier and the logic returns to the previous (current) state ignoring virtual column.
|
Could you rebase please? |
85e3145 to
b8c69f6
Compare
adamruzicka
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested together with the foreman_openscap PR, works well
|
Could you please squash the commits? |
Refs #38024 - Check if select_virt_col is allowed Refs #38024 - Refactor the same logic Refs #38024 - Reorder in case default scope with order
b8c69f6 to
80dfd83
Compare
|
Thanks, @adamruzicka, rebased / squashed. Although I'd like to see green tests just in case, but I don't think there will be related failures anyway 🤷 |
|
🍏 |
|
Thank you @ofedoren ! |
This is an alternative for #10368, tries to make ordering by columns, which are not part of actual table, possible.
This PR enables it for roles model, making possible to click on
lockedcolumn in roles index page and see the ordering, as well as doing so via API.Added an entry for developer_docs saying how to use it within plugins.
Thanks, @adamruzicka, for the idea!
@MariaAga, what do you think?
P.S. The only issue I see is that we'd need to update https://github.com/theforeman/foreman-tasks/blob/master/app/controllers/foreman_tasks/api/tasks_controller.rb#L195 to be compatible. Could be done as part of removal deprecated stuff.