Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lassoid/tiny_filter
Simple filtering for ActiveRecord, Sequel and enumerables.
https://github.com/lassoid/tiny_filter
filter filtering gem rails ruby ruby-on-rails
Last synced: about 1 month ago
JSON representation
Simple filtering for ActiveRecord, Sequel and enumerables.
- Host: GitHub
- URL: https://github.com/lassoid/tiny_filter
- Owner: lassoid
- License: mit
- Created: 2022-12-04T14:56:05.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-05-19T00:28:48.000Z (6 months ago)
- Last Synced: 2024-09-30T07:21:59.293Z (about 2 months ago)
- Topics: filter, filtering, gem, rails, ruby, ruby-on-rails
- Language: Ruby
- Homepage:
- Size: 68.4 KB
- Stars: 22
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# TinyFilter
[![Gem Version](https://img.shields.io/gem/v/tiny_filter?color=blue&label=version)](https://rubygems.org/gems/tiny_filter)
[![Gem downloads count](https://img.shields.io/gem/dt/tiny_filter)](https://rubygems.org/gems/tiny_filter)
[![Github Actions CI](https://github.com/lassoid/tiny_filter/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/lassoid/tiny_filter/actions/workflows/main.yml)TinyFilter is created to provide a simple object-oriented abstraction layer for filtering collections.
It is mainly purposed for ActiveRecord/Sequel models, but you can also use it with any enumerable.```ruby
Post.where(title: "Wow!").filter_by(from: 2.days.ago, to: 1.day.ago).order(:created_at)
```## Installation
1. Install the gem and add to the application's Gemfile by executing:
```shell
bundle add tiny_filter
```2. Generate an application filter as an entry point to all your future filters:
```shell
bin/rails g tiny_filter:install
```This will generate `ApplicationFilter` inside `app/filters` directory.
This directory is intended to store all your filters.## Adding a filter
To generate a filter class simply run `tiny_filter:filter` command.
For example, to create a filter class for `Post` with filters `from` and `to`, run:
```shell
bin/rails g tiny_filter:filter post from to
```This will generate the `PostFilter` class inside the `app/filters` directory with `from` and `to` filters.
Each filter is defined by calling `filters` method inside class body.
`filters` accepts two arguments:
- `key` - a filter name, used as identifier;
- `block` - a block with filter logic, that returns filtered collection and itself accepts two arguments:
- `scope` - a collection that should be filtered;
- `value` - a value for filtering.When you perform filtering, provided key indicate filter `key` and provided value is passed to `value` param in corresponding filter `block`.
`scope`s receive collections in a pipeline manner:
_first_ executed filter receives _original collection_,
_second and further_ receive the _return collection_ of the previous filter.To execute filtering, simply call `filter` with the initial scope and options provided.
```ruby
class UserFilter < ApplicationFilter
filters(:name) { |scope, value| scope.where(first_name: value) }
filters(:surname) { |scope, value| scope.where(last_name: value) }
endUserFilter.filter(User, name: "John", surname: "Doe")
# Which is equivalent to:
# User.where(first_name: "John").where(last_name: "Doe")
```Notice, that your filters _must_ return the same scope type as they accept.
It guarantees that scope behaves the same way as in other filters in this class.```ruby
filters(:title) { |scope, value| scope.where("title ILIKE ?", value) }# bad - scope is an ActiveRecord collection, but the return value is an array.
filters(:from) { |scope, value| scope.select { |e| e.created_at >= value } }# good - scope and return value are both ActiveRecord collections.
filters(:from) { |scope, value| scope.where("created_at >= ?", value) }
```Thus if the initial scope for filtering is an ActiveRecord collection,
it is a bad practice for filter to return not an ActiveRecord collection.
Otherwise you can face errors depending on the provided options order.## ORM integration
### ActiveRecord
TinyFilter provides a simple concern, that adds just one method `filter_by`,
that can be used in ActiveRecord method chaining.Just include `TinyFilter::Concern` in your model and that's all!
```ruby
class Post < ApplicationRecord
include TinyFilter::Concern
end
```Now you can use filtering everywhere in your model method chaining.
```ruby
Post.where(title: "something interesting").filter_by(from: 2.days.ago, to: 1.day.ago).order(:title)
Post.filter_by(from: 1.year.ago)
```### Sequel
The previously mentioned filter concern can also be used in Sequel models.
```ruby
class Artist < Sequel::Model
include TinyFilter::Concern
end
```Querying examples:
```ruby
Artist.where(name: "Kirill").filter_by(from: 2.days.ago, to: 1.day.ago).order(:name).all
Artist.filter_by(from: 1.year.ago).all
```### Naming convention
By default a filter class and a model are mapped by a _model name_ with a _suffix_ `Filter`.
For example, the model `My::Class` by default will use the `My::ClassFilter` as a filter class.You can customize this behavior by implementing a `filter_class` class method
with an appropriate class as a return value.```ruby
class My::Class < ApplicationRecord
# ...
def self.filter_class
CustomFilter
end
# ...
end
```## Using with Plain objects
You can use filters with Plain Old Ruby collections like so:
```ruby
options # filter options, for example: `{ from: 2.days.ago, to: 1.day.ago }`
collection # can be any Enumerable: array, hash, your custom collection, etc etcMyFilter.filter(collection, options)
```## Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/rspec` to run the tests.
You can also run `bin/rubocop` to lint the source code
and `bin/console` for an interactive prompt that will allow you to experiment.To install this gem onto your local machine, run `bin/rake install`.
To release a new version, update the version number in `version.rb`, and then run `bin/rake release`,
which will create a git tag for the version, push git commits and the created tag,
and push the `.gem` file to [rubygems.org](https://rubygems.org).## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/lassoid/tiny_filter.
This project is intended to be a safe, welcoming space for collaboration, and contributors
are expected to adhere to the [code of conduct](https://github.com/lassoid/tiny_filter/blob/main/CODE_OF_CONDUCT.md).## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
## Code of Conduct
Everyone interacting in the TinyFilter project's codebases, issue trackers, chat rooms and mailing lists
is expected to follow the [code of conduct](https://github.com/lassoid/tiny_filter/blob/main/CODE_OF_CONDUCT.md).