Ruby on Rails | Hotwire | RubyUI - Applying Complex Filters to a List of Complex Records
Imagine you're working on a supplier management system that handles supplier approvals. Each supplier has a range of associated data:
As you can see, we’re dealing with several types of filters: string, boolean, and multi-string selects.
Sure, you could write your SQL manually with a bunch of conditional IFs in your code—or even use ActiveRecord in a less structured way to get the result. And you'd probably make it work. But the result would be hard to read and even harder to maintain.
So, what’s the best way to solve this problem?
Let me introduce you to the extending method from the ActiveRecord::QueryMethods module. It helps you keep your filtering logic clean, modular, and maintainable. Below is a simple example showing how to handle each filter type.
# MAIN QUERY
Supplier
.where(buyer_id: user.buyer_id) # FILTERED SCOPE
.extending(SupplierScopes) # EXTENDING THE MODULE
.by_name_or_cnpj(name_or_cnpj: filters[:name_or_cnpj]) # TEXT
.by_started_by_me(user:, started_by_me: filters[:started_by_me]) # BOOLEAN
.by_status(status: filters[:status]) # ARRAY OF STRINGS
# SUPPLIER SCOPES MODULE
def by_name_or_cnpj(name_or_cnpj:)
name_or_cnpj.blank? ? self : fsearch(name_or_cnpj)
end
def by_started_by_me(user:, started_by_me:)
started_by_me.blank? ? self : where(started_by_email: user.email)
end
def by_status(status:)
status.blank? ? self : where(status:)
end
In production, the real implementation spans many lines, handling multiple filters and complex conditions. But for learning purposes, this example is more than enough to help you refactor your filters for better readability, scalability, and maintainability.
Cofounder @ Profit Leap and the 1st AI advisor for Entrepreneurs | CFO, CPA, Software Engineer
3wJean Pierry, omg this is SO needed for our db queries rn... wouldve saved me hours of headaches last week