Giter Club home page Giter Club logo

filterable's Introduction

Filterable

Build Status Code Climate

Filterable gem aims to simplify the process of filtering active record objects.

It provides an easy way to define filters on the model (without having to write scopes) and apply them on any active record collection.

See Defining Filters, Filtering objects and Using in Controller (Rails) for the main focus of the gem.

Installation

Add this line to your application's Gemfile:

gem 'toschas-filterable'

And then execute:

$ bundle

Or install it yourself as:

$ gem install toschas-filterable

Usage

Defining filters

Filterable provides filter_by method to ActiveRecord Objects which lets you define attributes to be filtered by:

class User < ActiveRecord::Base
  filter_by :active, :user_type
end

Filtering objects

Filterable will generate those methods on User class in the example above which can be used directly or passed to filter method as a hash of filters.

User.filter(by_active: true, by_user_type: 'customer') # returns users where active is true and user type is equal to 'customer'
User.by_active(true).by_user_type('customer') # same thing

Method is available on an AR Collection and it returns an AR collection so it can be chained with other methods.

User.where('email LIKE ?', '%@example.com').filter(by_active: true, by_user_type: 'customer')

or

User.filter(by_active: true, by_user_type: 'customer').where('email LIKE ?', '%@example.com')

Using in Controller (Rails)

You can pass a hash to the filter method, like the parameters hash in rails. It will ignore keys that are not defined in the model by default.

Important - you should always control parameters coming from the request, so the same applies to the filter method.

The right way in rails would be using strong parameters so you can control what can be passed to the filter.

class UsersController < ApplicationController
    def index
        @users = User.filter(filter_params)
    end
    
    protected
    
    def filter_params
        params.permit(:by_active, :by_user_type)
    end
end

Range Filters

For comparable types of fields (numeric values, date or datetime) from and to filters are also generated

class User < ActiveRecord::Base
    filter_by :registered_on, :tasks_assigned
end

Presuming that 'registered_on' is a date and 'tasks_assigned' is an integer, the following filters will be available:

  • by_registered_on (attribute value is equal to the value passed)
  • from_registered_on (attribute value is greather than the value passed)
  • to_registered_on (attribute value is smaller than the value passed)

and the same for 'tasks_assigned' attribute. So for example:

User.filter(from_tasks_assigned: 2) # returns users with more than 2 tasks assigned
User.filter(to_registered_on: Date.today) # retuns users registered before today

Filter by related model attribute

Filtering by attributes of another model is possible with joins option.

Names of joined models follow the same pattern as when defining relations: singular for 'belongs_to' and 'has_one', and plural for 'has_many'.

Filters must also be named accordingly: :user_email, joins: :user and :tasks_title, joins: :tasks

class Task < ActiveRecord::Base
    belongs_to :user
    filter_by :user_email, joins: :user 
end

class User < ActiveRecord::Base
    has_many :tasks
    filter_by :tasks_title, joins: :tasks
end
User.filter(by_tasks_title: 'test') # returns users where task title is 'test'
Task.filter(by_user_email: '[email protected]') # returns tasks where user email is '[email protected]'

Filtering through two or more related models works the same way, joins options must be specified the same way as passing it to .joins() method.

So if you want to filter Company by task title and you need to join tasks through users, format the option the same way you would tell ActiveRecord how to join the tables, and name the filter accordingly.

class Company < ActiveRecord::Base
    has_many :users
    filter_by :users_tasks_title, joins: { users: :tasks }
end

then

Company.filter(by_user_tasks_title: 'test')

Custom Filters

By passing custom: true option an empty custom filter will be defined.

It can than be overridden with a scope or a class method.

class Task < ActiveRecord::Base
    filter_by :fuzzy_title, custom: true # generates empty by_fuzzy_title filter
    
    # Overiding the filter with a class method or a scope
    scope :by_fuzzy_title, ->(title) { where('title LIKE ?', "%#{title}%") }
end

Custom filters support prefix option which can be a symbol, an array, or :none explicitly. If prefix option is not present by prefix will be used.

filter_by :custom_filter, custom: true # generates by_custom_filter filter
filter_by :custom_filter, custom: true, prefix: :where # generates where_custom_filter filter
filter_by :custom_filter, custom: true, prefix: [:by, :recent] # generates by_custom_filter and recent_custom_filter filters
filter_by :cutom_filter, custom: true, prefix: :none # generates custom_filter filter

joins option is ignored if custom: true is passed

prefix option is ignored if custom: true is not passed

Issues

Bug reports and feature proposals are always welcome. Feel free to open an issue.

Contributing

Please see contributing guide

License

The gem is available as open source under the terms of the MIT License.

filterable's People

Contributors

darjan avatar

Stargazers

 avatar Steven Traversi avatar Igor Baesse de Araujo avatar Milan Rawal avatar Igor Petkovic avatar Sava Vidakovic avatar

Watchers

James Cloos avatar  avatar Miloš Mihajlović avatar  avatar Sava Vidakovic avatar Milan Rawal avatar

filterable's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.