Skip to content
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

Remove Ransack from collection model; use new component instead for table header links. #2744

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

eddierubeiz
Copy link
Contributor

@eddierubeiz eddierubeiz commented Sep 11, 2024

Ref #2450

Background
Ransack did two things for us:

  • It took care of some aspects of searching, filtering and sorting.
  • It automatically kept track of the state of sorted tables and made it easy to create sortable column header links.

This PR separates these two tasks. The first is done in the controller; the second, inside a new component class.

More specifically:

1) Creating the list of collections to show:
Searching, filtering, sorting and pagination happen entirely in the #index method, using sane and legible code.

2) Table header links:

  • Default values for params are set in a new index_params method, which returns a permitted strongparams object.
  • This strongparams object is used to create a factory object named :link_maker.
  • :link_maker is instantiated in a before_action call, so it doesn't crowd the #index method.
  • :link_maker stores and encapsulates the current state of the sorted table.
  • In the template, :link_maker is then used to generate several SortedTableHeaderLinkComponent objects, one per sortable column, which are then rendered to display the actual links.

Tradeoffs
Since we intend to use this component in at least three (and likely more) admin controllers, this PR aims to simplify the model, controller and view, at the expense of slightly complicating the component.

  • The component, even with its internal class, is actually pretty simple considering what it does, and certainly much easier to understand than Ransack.
  • Likewise, If you ignore the component and its test, and just look at the modifications this PR makes to the model, controller and view: the improvement is obvious:
    • No mention of Ransack in the model
    • For sorting and filtering, we're using tried-and-true ActiveRecord patterns instead of magical and nested param names
    • Dev works the same way as prod.
    • Search now works in dev (see note below)
    • Sorting and filtering are decoupled from generating links
    • The code in the template is short and self-explanatory

Note: The #index method was not using permitted params, so we created an index_params method to return sanitized params that #index can use. These are then handed directly to the component code, along with keys that tell the component which keys important for what it's trying to do.

Note: Ransack search is currently broken in dev on the master branch.
This is one of the many reasons we want to get rid of it, but it's easy to forget about.
(Try going to http://localhost:3000/admin/works in dev on master and searching for Goat. You get an
ArgumentError in Admin::WorksController#index with error message Invalid search term q
unless you comment out
c.ignore_unknown_conditions = Rails.env.production?
in ransack.rb.

What this means
If you are testing this PR in dev, and note that the search is broken on the admin works page, that's not because this PR broke it. It's because it is broken in master and this PR does not modify the admin works page.

@eddierubeiz eddierubeiz changed the title [WIP] Remove Ransack from collection model; use new service class instead for table header links. [WIP] Remove Ransack from collection model; use new component instead for table header links. Sep 12, 2024
@eddierubeiz eddierubeiz self-assigned this Sep 13, 2024
@eddierubeiz eddierubeiz changed the title [WIP] Remove Ransack from collection model; use new component instead for table header links. Remove Ransack from collection model; use new component instead for table header links. Sep 17, 2024
@eddierubeiz eddierubeiz marked this pull request as ready for review September 17, 2024 21:54
@eddierubeiz eddierubeiz marked this pull request as draft September 19, 2024 12:59
@eddierubeiz eddierubeiz changed the title Remove Ransack from collection model; use new component instead for table header links. [WIP] Remove Ransack from collection model; use new component instead for table header links. Sep 19, 2024
@eddierubeiz eddierubeiz changed the title [WIP] Remove Ransack from collection model; use new component instead for table header links. Remove Ransack from collection model; use new component instead for table header links. Sep 19, 2024
@eddierubeiz eddierubeiz marked this pull request as ready for review September 19, 2024 13:44
@@ -30,9 +26,23 @@ def index
@department = params[:department]
end

scope = scope.order(Arel.sql("#{params[:sort_field]} #{params[:sort_order]}"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the link_maker handles this, so the knowledge about what the param keys are is in ONE place?

scope = link_maker.add_order(scope)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you think, nah?

@jrochkind
Copy link
Contributor

jrochkind commented Sep 19, 2024

I think this is a great approach, good work!

Some comments!

slight change to how we handle sort order
else
# For columns OTHER than the one the table is currently sorted by,
# clicking the title of the column will sort the table by that column,
# in an arbitrary order.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I understand, but what do you mean by "arbitrary"? WE only have two kinds, asc and desc, don't we know for sure which one we are doing? With "asc" being the default?

# Also sets default sort column and order.
# This does not actually perform any sorting or filtering.
def index_params
@index_params ||= Kithe::Parameters.new(params).permit(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to use Kithe::Parameters here, let's just use ordinary rails strong params. https://api.rubyonrails.org/classes/ActionController/StrongParameters.html

Which means this can just be params.permit...

restore ransack behavior of which order when changing sort field
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants