# Call scopes directly from your URL params: | |
# | |
# @products = Product.filter(params.slice(:status, :location, :starts_with)) | |
module Filterable | |
extend ActiveSupport::Concern | |
module ClassMethods | |
# Call the class methods with names based on the keys in <tt>filtering_params</tt> | |
# with their associated values. For example, "{ status: 'delayed' }" would call | |
# `filter_by_status('delayed')`. Most useful for calling named scopes from | |
# URL params. Make sure you don't pass stuff directly from the web without | |
# whitelisting only the params you care about first! | |
def filter(filtering_params) | |
results = self.where(nil) # create an anonymous scope | |
filtering_params.each do |key, value| | |
results = results.public_send("filter_by_#{key}", value) if value.present? | |
end | |
results | |
end | |
end | |
end |
This comment has been minimized.
This comment has been minimized.
This could be seriously dangerous if you don't whitelist the params in the controller:
|
This comment has been minimized.
This comment has been minimized.
@skateinmars If you look at the original blog. we only send that params that were sliced( filtered ) |
This comment has been minimized.
This comment has been minimized.
This is a pretty nice way of doing this sort of thing. @justinweiss, what would you do if you needed to do a bit of preprocessing on the params? For example, lets say I want to filter a Post model by Tags. My query string is |
This comment has been minimized.
This comment has been minimized.
Why don't you make a gem |
This comment has been minimized.
This comment has been minimized.
I think |
This comment has been minimized.
This comment has been minimized.
thanks @justinweiss! this is awesome!!! hope all is well w you. |
This comment has been minimized.
This comment has been minimized.
can this be included in the base class? which will then inherit ? |
This comment has been minimized.
This comment has been minimized.
Hi @justinweiss! And thanks for the gist |
This comment has been minimized.
This comment has been minimized.
work in rails 4 ?? |
This comment has been minimized.
This comment has been minimized.
Thanks for your code it worked for me right from the gist. Nonetheless, I've created a scope with 'joins' so the results could appear more than once. In your opinion, Should I include a 'distinct' in that scope only, or should that behavior be included globally in the filter method as in https://gist.github.com/gusridd/9e80f763bae56a425aff310eeef0ae0f ? |
This comment has been minimized.
This comment has been minimized.
That helped a lot. Thanks :) |
This comment has been minimized.
This comment has been minimized.
thanks but i have a doubt that how i can create scope for join table |
This comment has been minimized.
This comment has been minimized.
Thank for this gist, I use it often, but with some extras : cattr_accessor :filters
def available_filters(*filters)
self.filters ||= []
self.filters += scopes
self.filters.uniq!
end And in method filtering_params = filtering_params.symbolize_keys.slice(*self.filters) I use class Person < ActiveRecord::Base
[...]
available_scopes :name, :role, :age, :phone_number
[...]
end And, I use also the role definition on available_filters like this (not handled in my examples) : available_scopes :name, :role, :age, :phone_number, as: :admin
available_scopes :name, :role, as: :user |
This comment has been minimized.
This comment has been minimized.
For Join table (many to many through) class Item < ApplicationRecord
has_many :categorizations
has_many :categories, through: :categorizations
scope :category, ->(category) { Item.joins(:categories).where category: category }
scope :other, ->(other) { where other: other }
end |
This comment has been minimized.
This comment has been minimized.
Thank you so much! |
This comment has been minimized.
This comment has been minimized.
Thank you! |
This comment has been minimized.
This comment has been minimized.
@justinweiss Just upgraded to Ruby 2.6.0 and started getting an ArgumentError If I go back to the step before you put this into the Filterable module, the error disappears.
More context from my app. Given this snippet, post
It seems that my first line creates the issue, so the question would be how to preserve my With this option it resumes working (includes and order as well as filtering) without me modifying line 1.
|
This comment has been minimized.
This comment has been minimized.
@justinweiss Been looking at this some more this morning. The following also appears to work. Preserves filtering, preserves includes and order. Doesn't generate Argument Error.
Any insights? |
This comment has been minimized.
This comment has been minimized.
Got some advice from @shuriu on this error.
So, I renamed |
This comment has been minimized.
This comment has been minimized.
I ran into this issue also after upgrading to Ruby 2.6. I was able to get around this by renaming my |
This comment has been minimized.
This comment has been minimized.
My very own version:
|
This comment has been minimized.
This comment has been minimized.
Hi All, thanks inadvance for your support.. |
This comment has been minimized.
Thanks this is a really useful pattern. Bookmarked!