Skip to content

Commit

Permalink
Filterameter post additions
Browse files Browse the repository at this point in the history
Added sections for AR and testing as well as a couple other minor tweaks.
  • Loading branch information
toddkummer committed Oct 14, 2024
1 parent a0b96df commit 0e28876
Showing 1 changed file with 29 additions and 6 deletions.
35 changes: 29 additions & 6 deletions src/_posts/2024-10-09-filterameter.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ og_description: |
Handling filter parameters for index endpoints in Rails controllers can often be a repetitive and error-prone task. The Filterameter gem aims to simplify this process by providing a declarative way to define filters. In this post, we’ll explore how Filterameter can help you write cleaner and more maintainable code.
---

Handling filter parameters for index endpoints in Rails controllers can often be a repetitive and error-prone task. The Filterameter gem aims to simplify this process by providing a declarative way to define filters. In this post, we'll explore how Filterameter can help you write cleaner and more maintainable code.
Handling filter parameters for index endpoints in Rails controllers can often be a repetitive and error-prone task. The [Filterameter gem](https://github.com/RockSolt/filterameter) aims to simplify this process by providing a declarative way to define filters. In this post, we'll explore how Filterameter can help you write cleaner and more maintainable code.

### The Problem with Traditional Filtering

Expand All @@ -17,7 +17,7 @@ Consider the following typical controller action:
```ruby
def index
@films = Films.all
@films = @films.where(name: params[:name]) if params[:name]
@films = @films.where('name like ?', Film.sanitize_sql_like("%#{params[:name]}%")) if params[:name]
@films = @films.joins(:film_locations).merge(FilmLocations.where(location_id: params[:location_id])) if params[:location_id]
@films = @films.directed_by(params[:director_id]) if params[:director_id]
@films = @films.written_by(params[:writer_id]) if params[:writer_id]
Expand All @@ -29,8 +29,8 @@ end
The approach has several drawbacks:

- **Redundancy:** Each filter requires a separate conditional statement.
- **Maintainability**: Adding or modifying filters involves changing multiple lines of code.
- **Readability**: The logic can become hard to follow, especially with many filters.
- **Maintainability**: The logic can become hard to follow, especially with many filters.
- **Readability**: There is not a clear list of available filters.

### Introducing Filterameter

Expand Down Expand Up @@ -66,7 +66,7 @@ filter :actor_id, name: :acted_by

#### Matching Strings

A search for `thin` should return both _After the Thin Man_ and _Shadow of the Thin Man_.
Searching for partial matches (SQL's `like`) is a common task and easy with Filterameter:

```ruby
filter :name, partial: true
Expand Down Expand Up @@ -136,10 +136,33 @@ When an attribute is declared as a filter, it is also sortable by default. Non-f
sort :by_created_at
```

#### ActiveRecord Query

Filterameter leverages ActiveRecord to build queries, so there is no need to learn a new syntax. Additionally, the
`build_query_from_filters` method can take a starting query as an argument, which can be helpful for
includes or authorization restrictions.

```ruby
@films = build_query_from_filters(Films.includes(film_locations: :location))
```

#### Validating Declarations

Typos are real, but they won't make it past your test suite. A single test for each controller will validate your
declarations.

```ruby
# rspec
expect(WidgetsController.declarations_validator).to be_valid

# minitest
validator = WidgetsController.declarations_validator
assert_predicate validator, :valid?, -> { validator.errors }
```


### Conclusion

Filterameter provides a powerful and flexible way to handle filter parameters in Rails controllers. By using declarative filters, you can reduce boilerplate code, improve readability, and make your controllers easier to maintain. If you frequently deal with complex filtering logic, Filterameter is definitely worth a look.

Check out the [Filterameter GitHub repository](https://github.com/RockSolt/filterameter).
Check out the [Filterameter GitHub repository](https://github.com/RockSolt/filterameter) for all the details.

0 comments on commit 0e28876

Please sign in to comment.