jhund / filterrific Goto Github PK
View Code? Open in Web Editor NEWFilterrific is a Rails Engine plugin that makes it easy to filter, search, and sort your ActiveRecord lists.
Home Page: http://filterrific.clearcove.ca
License: MIT License
Filterrific is a Rails Engine plugin that makes it easy to filter, search, and sort your ActiveRecord lists.
Home Page: http://filterrific.clearcove.ca
License: MIT License
@jhund I'm having some trouble wrapping my head around how I would do this. I want my model to have an hstore with user-configurable fields. I then want the user to be able to filter on each field. Can it work?
Thanks!
I often find myself wishing I had an easy way of grouping all the form options for all of filterrific's select boxes, and have taken to doing the following:
@filterrific = Filterrific.new(ModelClass, params[:filterrific])
class << @filterrific
attr_accessor :options
end
@filterrific.options = {
category_ids: ModelClass.joins(:category).distinct.pluck('categories.id', 'category.name'),
# A bunch of other filter options here
}
Then in the view:
<%= f.select :with_category_id, @filterrific.options[:category_ids], 'data-placeholder' => 'Category' %>
Rather than having to have a @category_ids
instance variable, and whatever other instance variables are needed. Would you be open to something like this making it into core?
If so I'll put a PR together :)
Having trouble getting this gem to work. I am getting the error "ERROR: undefined method `empty?' for nil:NilClass", it seems like the problem comes from the f.select in my form.
I have attached the relevant sections below. I have been trying to get this gem to work all day with no luck. Great documentation, but just can't get it to work.
My Application model:
class Application < ActiveRecord::Base
belongs_to :user
belongs_to :project
filterrific(
default_settings: { sorted_by: 'created_at_desc' },
filter_names: %w[
with_angelbacker_id
sorted_by
]
)
scope :sorted_by, lambda { |sort_option|
# extract the sort direction from the param value.
direction = (sort_option =~ /desc$/) ? 'desc' : 'asc'
case sort_option.to_s
when /^created_at_/
# Simple sort on the created_at column.
# Make sure to include the table name to avoid ambiguous column names.
# Joining on other tables is quite common in Filterrific, and almost
# every ActiveRecord table has a 'created_at' column.
order("applications.created_at desc")
else
raise(ArgumentError, "Invalid sort option: #{ sort_option.inspect }")
end
}
scope :with_angelbacker_id, lambda { |flag|
return nil if 0 == flag # checkbox unchecked
where(:angelbacker => flag)
}
def self.options_for_sorted_by
[
['Angelbacker', 'created_at_desc']
]
end
end
My Project controller model:
@filterrific = Filterrific.new(Application, params[:filterrific] || session[:filterrific_applications])
@applications = Application.filterrific_find(@filterrific).page(params[:page])
session[:filterrific_applications] = @filterrific.to_hash
respond_to do |format|
format.html
format.js
end
My Project view:
<%= form_for @filterrific do |f| %>
<div>
Angelbacker
<%= f.select(
:with_angelbacker_id,
@filterrific.select_options[:with_angelbacker],
{ include_blank: '- Any -' }
) %>
<%# See below for the Country.options_for_select presenter method %>
</div>
<div>
Sorted by
<%= f.select(:sorted_by, @filterrific.select_options[:sorted_by]) %>
<%# See below for the Student.options_for_sorted_by presenter method %>
</div>
<div>
<%= link_to(
'Reset filters',
reset_filterrific_applications_path,
) %>
</div>
<%# add an automated spinner to your form when the list is refreshed %>
<%= render_filterrific_spinner %>
<% end %>
<%= render(
'list',
locals: { applications: @applications }
) %>
I want to show the filterrific form in landing page of my application. How do I make the form respond to different controller action?
Can you suggest a way to merge two mutually exclusive scopes using filterrific? No problem utilizing individual filters/scopes, but I'd like to have at the end of the scope chain .merge(final_named_scope)
In the ParamSet
class when the value looks like an int we cast it as an int
ex
[1] > condition_filterrific_params { 'filter_array_int' => %w[1 2 3], 'filter_int' => '42' }
=> { 'filter_array_int' => [1, 2, 3], 'filter_int' => 42 }
which is fine most of the time.
however this might not always be what we want, for example, i want to look for a basic search on :phone
in a User
activerecord, I might do:
class User < ActiveRecord::Base
scope :with__phone__ilike, ->(value) { where("phone ILIKE ?", "%#{value}%") }
end
# let's say in db we have the following users
# User(phone: '12346789')
# User(phone: '12340067')
class SearchController < ActionController
def search_phone
filt = initialize_filterrific(User, params)
users = User.filterrific_find(filt)
render json: users.pluck(:phone)
end
end
# calling the route with: params = { 'with__phone__ilike' => '067' }
# will sanitize the filter to { 'with__phone__ilike' => 67 }
# and returns false positive => ['12346789', '12340067']
in that case the leading 0 was important in the filter value and was filter out because it was casted as int.
Same problem occurs if it appears in an array
I think we might expect information not to be dropped (in that case the leading zero)
something like
[1] > condition_filterrific_params { 'filter_array_int' => %w[1 2 3 03], 'filter_not_quite_int' => '042', 'filter_int' => '42' }
=> { 'filter_array_int' => [1, 2, 3, '03'], 'filter_not_quite_int' => '042', 'filter_int' => 42 }
this could be achieved by using a different regex such as /^[1-9]\d*$/
. Replacing that code by
def condition_filterrific_params(fp)
fp.each do |key, val|
case
when val.is_a?(Proc)
# evaulate Procs
fp[key] = val.call
when val.is_a?(Array)
# type cast integers in the array
fp[key] = fp[key].map { |e| e =~ /^[1-9]\d*$/ ? e.to_i : e }
when val =~ /^[1-9]\d*$/
# type cast integer
fp[key] = fp[key].to_i
end
end
fp
end
``
I was wondering if there's a way to check if the filters are set in the view. I'd like to provide a hint to my users that the view is currently filtered.
We're using https://github.com/Sology/smart_listing right now for our lists. I like the simplicity of this gem but the one thing it is missing is sortable headers. Any chance you are planning to add this feature?
I have a single controller with two separate actions each using filterriific.
What is the best pattern to ensure that each action has their own filters in session? Me's a noob.
Hi,
New to filterrific
, I want to display a filter form.
Base on rails 4.2
(ruby 2.1
) and erb
, the form seem not to be displayed (neither visible nor in the DOM) when I add this into my view
<% form_for @filterrific, html: {id: 'filterrific_filter'} do |f| %>
<select>
<% @filterrific.select_options[:per_event].each do |name, id| %>
<option value="<%=id%>"><%=name%></option>
<% end %>
</select>
<% end %>
even this
<% form_for @filterrific, html: {id: 'filterrific_filter'} do |f| %>
<select>
<%= f.select :per_event, @filterrific.select_options[:per_event] %>
</select>
<% end %>
only this
<select>
<% @filterrific.select_options[:per_event].each do |id,name| %>
<option value="<%=id%>"><%=name%></option>
<% end %>
</select
could diplay my select.
select_options[:per_event]
contains an array of element I want to filter with
I could not find any doc with rails 4, am I missi,ng something ?
Regards,
If you use:
<%= form_for_filterrific @filterrific, as: :filter do |f| %>
<% end %>
the params prefix will be filter
but the reset_filterrific_url()
uses the default filterrific
one:
?filterrific[reset_filterrific]=true
instead of:
?filter[reset_filterrific]=true
I think that an :as
option in the helper would suffice.
Keep getting "undefined method" error for my model.
Though it worked for a while. Only thing I did after was install searchkick. Though I uninstalled both and reinstalled only filterrific, to no avail.
I'm using rails 4, filterrific 1.3.1 and ruby 2.0.0
Error message:
undefined method `filterrific' for #Class:0x007fb710eee7a0
Extracted source (around line #2):
class Listing < ActiveRecord::Base
filterrific(
default_settings: { sorted_by: 'created_at_desc' },
filter_names: [
:sorted_by,
:search_query,
Here's the stack trace:
activerecord (4.1.4) lib/active_record/dynamic_matchers.rb:26:in method_missing' app/models/listing.rb:2:in
class:Listing'
app/models/listing.rb:1:in <top (required)>' activesupport (4.1.4) lib/active_support/dependencies.rb:443:in
load'
activesupport (4.1.4) lib/active_support/dependencies.rb:443:in block in load_file' activesupport (4.1.4) lib/active_support/dependencies.rb:633:in
new_constants_in'
activesupport (4.1.4) lib/active_support/dependencies.rb:442:in load_file' activesupport (4.1.4) lib/active_support/dependencies.rb:342:in
require_or_load'
activesupport (4.1.4) lib/active_support/dependencies.rb:480:in load_missing_constant' activesupport (4.1.4) lib/active_support/dependencies.rb:180:in
const_missing'
activesupport (4.1.4) lib/active_support/inflector/methods.rb:238:in const_get' activesupport (4.1.4) lib/active_support/inflector/methods.rb:238:in
block in constantize'
activesupport (4.1.4) lib/active_support/inflector/methods.rb:236:in each' activesupport (4.1.4) lib/active_support/inflector/methods.rb:236:in
inject'
activesupport (4.1.4) lib/active_support/inflector/methods.rb:236:in constantize' activesupport (4.1.4) lib/active_support/core_ext/string/inflections.rb:66:in
constantize'
cancan (1.6.10) lib/cancan/controller_resource.rb:147:in resource_class' cancan (1.6.10) lib/cancan/controller_resource.rb:187:in
resource_base'
cancan (1.6.10) lib/cancan/controller_resource.rb:77:in load_collection?' cancan (1.6.10) lib/cancan/controller_resource.rb:33:in
load_resource'
cancan (1.6.10) lib/cancan/controller_resource.rb:25:in load_and_authorize_resource' cancan (1.6.10) lib/cancan/controller_resource.rb:10:in
block in add_before_filter'
activesupport (4.1.4) lib/active_support/callbacks.rb:440:in instance_exec' activesupport (4.1.4) lib/active_support/callbacks.rb:440:in
block in make_lambda'
activesupport (4.1.4) lib/active_support/callbacks.rb:160:in call' activesupport (4.1.4) lib/active_support/callbacks.rb:160:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:149:in call' activesupport (4.1.4) lib/active_support/callbacks.rb:149:in
block in halting_and_conditional'
activesupport (4.1.4) lib/active_support/callbacks.rb:166:in call' activesupport (4.1.4) lib/active_support/callbacks.rb:166:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:229:in call' activesupport (4.1.4) lib/active_support/callbacks.rb:229:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:229:in call' activesupport (4.1.4) lib/active_support/callbacks.rb:229:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:166:in call' activesupport (4.1.4) lib/active_support/callbacks.rb:166:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:166:in call' activesupport (4.1.4) lib/active_support/callbacks.rb:166:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:166:in call' activesupport (4.1.4) lib/active_support/callbacks.rb:166:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:86:in call' activesupport (4.1.4) lib/active_support/callbacks.rb:86:in
run_callbacks'
actionpack (4.1.4) lib/abstract_controller/callbacks.rb:19:in process_action' actionpack (4.1.4) lib/action_controller/metal/rescue.rb:29:in
process_action'
actionpack (4.1.4) lib/action_controller/metal/instrumentation.rb:31:in block in process_action' activesupport (4.1.4) lib/active_support/notifications.rb:159:in
block in instrument'
activesupport (4.1.4) lib/active_support/notifications/instrumenter.rb:20:in instrument' activesupport (4.1.4) lib/active_support/notifications.rb:159:in
instrument'
actionpack (4.1.4) lib/action_controller/metal/instrumentation.rb:30:in process_action' actionpack (4.1.4) lib/action_controller/metal/params_wrapper.rb:250:in
process_action'
searchkick (0.8.3) lib/searchkick/logging.rb:107:in process_action' activerecord (4.1.4) lib/active_record/railties/controller_runtime.rb:18:in
process_action'
actionpack (4.1.4) lib/abstract_controller/base.rb:136:in process' actionview (4.1.4) lib/action_view/rendering.rb:30:in
process'
actionpack (4.1.4) lib/action_controller/metal.rb:196:in dispatch' actionpack (4.1.4) lib/action_controller/metal/rack_delegation.rb:13:in
dispatch'
actionpack (4.1.4) lib/action_controller/metal.rb:232:in block in action' actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:82:in
call'
actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:82:in dispatch' actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:50:in
call'
actionpack (4.1.4) lib/action_dispatch/journey/router.rb:71:in block in call' actionpack (4.1.4) lib/action_dispatch/journey/router.rb:59:in
each'
actionpack (4.1.4) lib/action_dispatch/journey/router.rb:59:in call' actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:678:in
call'
rack-pjax (0.8.0) lib/rack/pjax.rb:12:in call' warden (1.2.3) lib/warden/manager.rb:35:in
block in call'
warden (1.2.3) lib/warden/manager.rb:34:in catch' warden (1.2.3) lib/warden/manager.rb:34:in
call'
rack (1.5.2) lib/rack/etag.rb:23:in call' rack (1.5.2) lib/rack/conditionalget.rb:25:in
call'
rack (1.5.2) lib/rack/head.rb:11:in call' remotipart (1.2.1) lib/remotipart/middleware.rb:27:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/params_parser.rb:27:in call' actionpack (4.1.4) lib/action_dispatch/middleware/flash.rb:254:in
call'
rack (1.5.2) lib/rack/session/abstract/id.rb:225:in context' rack (1.5.2) lib/rack/session/abstract/id.rb:220:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/cookies.rb:560:in call' activerecord (4.1.4) lib/active_record/query_cache.rb:36:in
call'
activerecord (4.1.4) lib/active_record/connection_adapters/abstract/connection_pool.rb:621:in call' activerecord (4.1.4) lib/active_record/migration.rb:380:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/callbacks.rb:29:in block in call' activesupport (4.1.4) lib/active_support/callbacks.rb:82:in
run_callbacks'
actionpack (4.1.4) lib/action_dispatch/middleware/callbacks.rb:27:in call' actionpack (4.1.4) lib/action_dispatch/middleware/reloader.rb:73:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/remote_ip.rb:76:in call' actionpack (4.1.4) lib/action_dispatch/middleware/debug_exceptions.rb:17:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/show_exceptions.rb:30:in call' railties (4.1.4) lib/rails/rack/logger.rb:38:in
call_app'
railties (4.1.4) lib/rails/rack/logger.rb:20:in block in call' activesupport (4.1.4) lib/active_support/tagged_logging.rb:68:in
block in tagged'
activesupport (4.1.4) lib/active_support/tagged_logging.rb:26:in tagged' activesupport (4.1.4) lib/active_support/tagged_logging.rb:68:in
tagged'
railties (4.1.4) lib/rails/rack/logger.rb:20:in call' actionpack (4.1.4) lib/action_dispatch/middleware/request_id.rb:21:in
call'
rack (1.5.2) lib/rack/methodoverride.rb:21:in call' rack (1.5.2) lib/rack/runtime.rb:17:in
call'
activesupport (4.1.4) lib/active_support/cache/strategy/local_cache_middleware.rb:26:in call' rack (1.5.2) lib/rack/lock.rb:17:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/static.rb:64:in call' rack (1.5.2) lib/rack/sendfile.rb:112:in
call'
railties (4.1.4) lib/rails/engine.rb:514:in call' railties (4.1.4) lib/rails/application.rb:144:in
call'
rack (1.5.2) lib/rack/lock.rb:17:in call' rack (1.5.2) lib/rack/content_length.rb:14:in
call'
rack (1.5.2) lib/rack/handler/webrick.rb:60:in service' /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/webrick/httpserver.rb:138:in
service'
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/webrick/httpserver.rb:94:in run' /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/webrick/server.rb:295:in
block in start_thread'
Please let me know if there's any more information I can provide. I'm a noob.
Need to make sure it's included in the corresponding rake task.
I have been trying to figure out the view necessary to make the many-to-many relation work and I can't figure it out.
I have the scope working (tested by setting default values).
I am using the scope mentioned here http://filterrific.clearcove.ca/pages/active_record_scope_patterns.html#filter_by_existence_many_to_many
I am trying to either have checkboxes or a multi select list.
I can't seem to find an answer anywhere else online.
I am trying to export the filtered data to a .csv file but all I get is all the records from the database. here is my link_to.
<%= link_to "Exporter", users_path(:format => :csv, :filterrific => params[:filterrific]) %>
Can't figure out How to get the filtered params...
Any idea would be great
Thanks
I hoping to use this gem to replace our current filtering system because it looks really awesome. The one thing that we need to be able to do is pass filter parameters in to that page through a url. That way we can send a user to the exact set of results they may be looking for. Is there a way to add ?search_query=Chris or whatever to the end of the page url?
Chainning the existing scopes with Filterrific doesn't work when the filter is empty.
Here is a simple example:
# Assuming a feedback model having a rating (integer) column
class Feedback < ActiveRecord::Base
filterrific(filter_names: [:with_rating])
scope :no_low_rating, -> { where('rating > ?', 2) }
scope :with_rating, ->(keys) { where(rating: [*keys.to_s.split(',')]) }
end
# When there is a filter
filter = Filterrific.new(Feedback, with_rating: 2)
# This will work
Feedback.no_low_rating.filterrific_find(filter)
# When there is no filter
filter = Filterrific.new(Feedback, {})
# This won't work, it'll give me the ActiveRecord class Feedback
Feedback.no_low_rating.filterrific_find(filter)
# This will work but is damn ugly
Feedback.filterrific_find(filter).all.scoping { Feedback.no_low_rating }
A fix seems to be the following (ruby 2.0.0 rails 4.1)
module Filterrific
module ActiveRecordExtension
def filterrific_find(filterrific_param_set)
unless filterrific_param_set.is_a?(Filterrific::ParamSet)
raise(ArgumentError, "Invalid Filterrific::ParamSet: #{ filterrific_param_set.inspect }")
end
# set initial ar_proxy to including class
ar_proxy = self.all # CHANGED `self` TO `self.all`
# apply filterrific params
self.filterrific_filter_names.each do |filter_name|
filter_param = filterrific_param_set.send(filter_name)
next if filter_param.blank? # skip blank filter_params
ar_proxy = ar_proxy.send(filter_name, filter_param)
end
ar_proxy
end
end
end
It's seems to work for the other cases:
Hi, first of all I'd like like to thank you for this great gem. I'm actually looking for a way to perform searches with a search button only. I have too many input fields and a google maps in my _list partial, having a new request each time a select input has been changed isn't a good thing I guess. How can I implement a button ? Thanks in advance for your answer
I have no idea why I'm getting this error. Below is my code.
Leads Controller (There's some extra code in here that needs to be cleaned up, but I just pasted it all.
class LeadsController < ApplicationController
def index
@user = current_user
@leads = Lead.where(reviewed: true).order(:id).page(params[:page])
@filterrific = Filterrific.new(Lead, params[:filterrific] || session[:filterrific_leads])
@filterrific.select_options = { with_action_type_id: Actiontype.options_for_select }
@user_leads = @user.leads.filterrific_find(@filterrific).page params[:page]
session[:filterrific_leads] = @filterrific.to_hash
@actiontypes = Actiontype.all
@nonleadactions = Nonleadaction.all
@inquiryreasons = Reasoninquiry.all
@actual_leads = Lead.where(:reasoninquiry_id => [1, 2, 3])
@bymonthleads = @actual_leads.group_by { |lead| lead.created_at.beginning_of_month.strftime("%B")}
respond_to do |format|
format.html
format.js
end
end
def reset_filterrific
session[:filterrific_leads] = nil
redirect_to action: :index
end
Lead Model
class Lead < ActiveRecord::Base
filterrific(
default_settings: { sorted_by: 'actiontype_id_desc' },
filter_names: [
:sorted_by,
:with_action_type_id,
:with_inquiry_type_id
]
)
belongs_to :user
has_one :actiontype
has_one :reasoninquiry
has_one :nonleadaction
scope :sorted_by, lambda { |actiontypes|
order("leads.created_at desc")
}
scope :with_action_type_id, lambda { |actiontypes|
where(actiontype_id: [*actiontypes])
where(reviewed: true)
}
scope :with_inquiry_type_id, lambda { |inquiry_type_ids|
# Filters students with any of the given country_ids
}
def self.filter_by_reviewed_status(status)
case status
when nil then scoped
when 'true' then where(reviewed: true)
when 'false' then where(reviewed: false)
end
end
end
index.html.erb (again, messy and needs to be cleaned up, but I don't know if something in here is messing it up)
<%= form_for @filterrific do |f| %>
<div class="row-fluid">
<div class="widget-half span6">
<label>Start Date:</label>
<input class="filters" type="text" id="startDate" name="sd" value="30 days ago">
</div>
<div class="widget-half span6">
<label>End Date:</label>
<input class="filters" type="text" id="endDate" name="ed" value="today" />
</div>
</div>
<div class="form-actions">
<div id="report-callback"></div>
<div id="select-action">
<input type="submit" class="btn btn-green btn-large btn-wide pull-right" value="Generate Report"/>
</div>
<div id="email-popup" style="display: none">
<p>We'll email this to you in a few minutes, where should we send it (separate Emails by commas)?</p>
<textarea name="emails" class="input-block-level"></textarea>
<input type="button" class="btn btn-green btn-large btn-wide pull-right" value="Send Report" id="send-report"/>
<input type="button" class="btn btn-grey btn-large btn-wide pull-left" value="Cancel" id="cancel-report"/>
</div>
<% @filterrific.select_options[:with_action_type_id].each do |c| %>
<%= check_box_tag("filterrific[with_action_type_id][]",c) %>
<%=h c %>
<% end %>
<%= f.select :with_action_type_id, @filterrific.select_options[:with_action_type_id], include_blank: true %>
</div>
<% end %>
Actiontype model
belongs_to :lead
def self.options_for_select
order('action_type').map { |e| [e.action_type, e.id] }
end
What runs in the server log when I do the request:
Started GET "/leads" for 127.0.0.1 at 2014-08-06 16:55:20 -0400
Processing by LeadsController#index as HTML
←[1m←[36mUser Load (0.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users
"."id" = ? LIMIT 1←[0m [["id", 3]]
←[1m←[35mActiontype Load (0.0ms)←[0m SELECT "actiontypes".* FROM "actiontypes
" ORDER BY action_type
Completed 500 Internal Server Error in 5ms
ArgumentError (wrong number of arguments (0 for 1)):
app/controllers/leads_controller.rb:8:in `index'
Rendered C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/actionpack-4.0.2
/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.0ms)
Rendered C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/actionpack-4.0.2
/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.0ms)
Rendered C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/actionpack-4.0.2
/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.0
ms)
Rendered C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/actionpack-4.0.2
/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues
/layout (29.0ms)
Hi,
I want to use filterrific on a new project but I want to make sure that I set the database up correctly.
I want my users to be able to input which language(s) they speak. ex: User 1 speaks English, French, Spanish.
I want people to be able to filter the search using multiple languages. Ex: find all users that speak both English and Spanish. I figured that would be done via a drop-down with check boxes.
What is the best way to set this up so that search/filtering is as fast as possible? Should each language be in a separate field ex: language_1 contains English, language_2 contains Spanish, etc. or can I save the languages in an array under a single field ex: language contains [English, Spanish, French]
Thanks for any feedback. I am just building out the app and don't want to get too far down a path that might make things slow.
Let's say you have two ActiveRecord class with one inheriting another
ex:
class WorkaholicDaddy < ActiveRecord::Base
filterrific(available_filters: [:millionaire, :sillicon_valley])
end
class DigitalBoy < WorkaholicDaddy
filterrific(available_filters: [:botox_injection, :fake_nails])
end
puts WorkaholicDaddy.filterrific_available_filters
# => botox_injection
# => fake_nails
puts DigitalBoy.filterrific_available_filters
# => botox_injection
# => fake_nails
Then the filterific_available_filters
of the lastest loaded class will override the first one.
That's not great.
This is due to the fact that the filterrific_available_filters is a class variable (see https://github.com/jhund/filterrific/blob/master/lib/filterrific/active_record_extension.rb#L22-L23). If it was a class instance variable it would work fine.
see https://stackoverflow.com/questions/15773552/ruby-class-instance-variable-vs-class-variable
I copied the sample and updated the sample code and adapted it.
Using filterrific 1.2.0
in location.rb
filterrific(
:default_settings => { :sorted_by => 'name_asc' },
:filter_names => %w[
sorted_by
search_query
with_zone_id
]
)
in location_controller.rb
def index
@filterrific = Filterrific.new(Location, params[:filterrific])
@locations = Location.filterrific_find(@filterrific).page(params[:page])
respond_to do |format|
format.html
format.js
end
end
in index.html.erb
<%= form_for @filterrific do |f| %>
I get an error message for the above line
"where line #3 raised:
wrong number of arguments (0 for 1)"
I cannot get to the root cause for this problem. Any help appreciated
I use multiple select for filter by status and I would like to add option "by blank'.
But when I add ['by blank', nil]
to collection then in html i have blank value in option element.
I have workaround solution, I add ['by blank', 'nil']
to collection and in scope replace 'nil'
to nil
.
scope:
scope :with_status_id, lambda { |status_ids|
ids = status_ids.dup
idx = status_ids.index { |o| o == 'nil' }
ids[idx] = nil unless idx.nil?
where(status_id: [*ids]) unless ids == [""]
}
Is there any better way to filter by nil
value?
Could we please have some documentation on how to scope an habtm relation? The examples work with has_many_through, but I cannot find any help to scope habtm.
For example on a bloglike application, where the post model has and belongs to many tags, I would like to have some examples on filtering posts by tags or by tags category.
Is there a way to do that?
Hello,
I'm not sure if this is how Filterrific works or if I'm doing something wrong.
I have two select
tags set as multiple: true
. When filterrific submits the data through ajax it takes the value from all the selects, which is fine. But if one of them is untouched/default it takes the value as nil
.. which causes the results to return empty.
^ No matter if I touch the client
select or not, it submits as nil
.
If both selects
are normal, with single value, works fine. The issue only happens when it has multiple values. Even by selecting - Any - as default doesn't return as it should.
I basically want to be able to search all my projects that have status Live
from all clients.
Hey, I keep getting this error from my select field.
Here are snippets of my code:
offer.rb
belongs_to :client
scope :with_client_id, -> { where(:client_id => client.id) }
scope :with_status, -> { where(:status => status) }
filterrific(
filter_names: [
:with_client_id,
:with_status,
:with_created_at_gte
]
)
offers_controller.rb
def index
@filterrific = Filterrific.new( Offer, params[:filterrific] || session[:filterrific_offers])
@offers = Offer.filterrific_find(@filterrific)
respond_to do |format|
format.html
format.js
end
end
index.html.erb
<%= form_for @filterrific do |f| %>
Can you please give me a hint on why this error occurs?
Thanks!
Hi,
I'm using the demo source with sqlite3, and I don't get the sort-by-country-name working. I get the following error.
SELECT "students".* FROM "students" WHERE "students"."country_id" = 6 ORDER BY LOWER(countries.name) asc LIMIT 10 OFFSET 0
SQLite3::SQLException: no such column: countries.name: SELECT "students".* FROM "students" WHERE "students"."country_id" = 6 ORDER BY LOWER(countries.name) asc LIMIT 10 OFFSET 0
Rendered students/_list.html.haml (8.3ms)
Rendered students/index.js.erb (10.9ms)
Completed 500 Internal Server Error in 21ms
Is this a sqlite problem? How do I fix this?
Thanks!
At least under Rails 4.2.0 it is wrong. In the documentation under http://filterrific.clearcove.ca/pages/active_record_scope_patterns.html#filter_by_existence_has_many you say to use
scope :with_comments, lambda {
where(
'EXISTS (SELECT 1 FROM students, comments WHERE students.id = comments.student_id)'
)
}
which "finds all students who have posted at least one comment."
This is not true, the code is translated into
SELECT "students".* FROM "students" WHERE ( EXISTS (SELECT 1 from students, comments WHERE students.id = comments.student_id)
So the WHERE-predicate is independent from the row of the outer "students" column and this way you get either the whole students table, if there is at least one student with a comment, or else an empty result set.
A fix for this would be to use
scope :with_comments, lambda {
where(
'EXISTS (SELECT 1 FROM comments WHERE students.id = comments.student_id)'
)
}
(so without the additional "FROM students" in the inner query) which translates to
SELECT "students".* FROM "students" WHERE ( EXISTS (SELECT 1 from comments WHERE students.id = comments.student_id)
Analogous for the "non existence" part.
I have two views. The first one runs filterrific with a text input and a select input. The second view has a text input and a button. I want the button to link to the first view with the input value passed to the filter. However, when I set the initial value of the filter input, filterrific observer doesn't detect it. I need to update the text input again to make the page show the correct result.
<%= f.text_field(:search_query, :value => params[:q], class: 'filterrific-periodically-observed typeahead') %>
Could someone give example with checkboxes?
Hi There,
I'm trying to set up a filtering/search engine using Filterrific.
So that you can get an idea of how the front-end operates:
Here is my model:
class Supplier < ActiveRecord::Base
# Supplier Admin Logins
devise :database_authenticatable, :timeoutable
# Search Engine
searchkick autocomplete: ['name']
# Paperclip
has_attached_file :image, :styles => { :full => "738x232#", :medium => "157x117#", :thumb => "200x85#" }, :default_url => "/assets/no-image-logo.png"
process_in_background :image, :processing_image_url => "/assets/image_processing.jpg"
# Validations
validates :email, :location, :phone, :website, :name, :available, :about, presence: true
# Associations
has_many :products, primary_key: :id, foreign_key: :supplier_id
has_many :supplier_images, primary_key: :id, foreign_key: :supplier_id, dependent: :destroy
has_many :supplier_comments, primary_key: :id, foreign_key: :supplier_id, dependent: :destroy
has_many :supplier_features, primary_key: :id, foreign_key: :supplier_id
has_many :supplier_enquiries, primary_key: :id, foreign_key: :supplier_id
# Allowed Attributes
attr_accessible :email, :location, :password, :phone, :website, :name, :image, :available, :contact_email, :facebook, :twitter, :pinterest, :board_limit, :is_authorized, :is_premium, :about, :supplier_images_attributes
accepts_nested_attributes_for :supplier_images
# Filterrific Filtering
filterrific(
:default_settings => { :sorted_by => 'name_asc' },
:filter_names => [
:sorted_by,
:search_query,
:with_categories,
:with_locations
]
)
scope :sorted_by, lambda { |sort_option|
# extract the sort direction from the param value.
direction = (sort_option =~ /desc$/) ? 'desc' : 'asc'
case sort_option.to_s
when /^name/
# Simple sort on the created_at column.
# Make sure to include the table name to avoid ambiguous column names.
# Joining on other tables is quite common in Filterrific, and almost
# every ActiveRecord table has a 'created_at' column.
order("suppliers.name #{ direction }")
when /^created_at_/
order("suppliers.created_at #{ direction }")
else
raise(ArgumentError, "Invalid sort option: #{ sort_option.inspect }")
end
}
scope :search_query, lambda { |query|
# Searches the students table on the 'first_name' and 'last_name' columns.
# Matches using LIKE, automatically appends '%' to each term.
# LIKE is case INsensitive with MySQL, however it is case
# sensitive with PostGreSQL. To make it work in both worlds,
# we downcase everything.
return nil if query.blank?
supplier_ids = self.search(query).map(&:id)
return nil if supplier_ids.empty?
where(id: supplier_ids)
}
scope :with_categories, lambda { |category_ids|
return nil if category_ids.blank?
formatted_category_ids = []
category_ids.each do |key, value|
formatted_category_ids << key.to_i if value.to_i == 1
end
return nil if formatted_category_ids.blank?
# Get all Suppliers that have Products in the supplied Categories
@suppliers = Supplier.joins(:products).where(products: { category_id: formatted_category_ids}).uniq!
# Array of valid supplier ids
valid_suppliers = []
# Loop over all the suppliers
@suppliers.each do |s|
catch(:invalid_supplier) do
# Loop over each category id
formatted_category_ids.each do |ci|
# If supplier does not have a product in this category,
# throw :invalid_supplier symbol to prevent adding supplier to array
throw :invalid_supplier if !s.products.where(category_id: ci).any?
end
# If symbol has not been thrown, save the suppliers id
valid_suppliers << s.id
end
end
return nil if valid_suppliers.empty?
# Return relation of suppliers
where(id: valid_suppliers)
}
scope :with_locations, lambda { |location_ids|
return nil if location_ids.blank?
formatted_location_ids = []
location_ids.each do |key, value|
formatted_location_ids << key.to_i if value.to_i == 1
end
return nil if formatted_location_ids.blank?
# Get all products from this supplier, in this location
@suppliers = Supplier.joins(products: :locations).where(locations: {id: formatted_location_ids}).uniq!
valid_suppliers = []
# Loop over each supplier and make sure they have at least one product in every location
@suppliers.each do |s|
catch(:invalid_supplier) do
# Loop over each category id
formatted_location_ids.each do |li|
# If supplier does not have a product in this category,
# throw :invalid_supplier symbol to prevent adding supplier to array
throw :invalid_supplier if !s.products.joins(:locations).where('locations.id = ?', li).any?
end
# If symbol has not been thrown, save the suppliers id
valid_suppliers << s.id
end
end
return nil if valid_suppliers.empty?
# Return relation
where(id: valid_suppliers)
}
def self.options_for_sorted_by
[
['Name Ascending (A-Z)', 'name_asc'],
['Name Descending (Z-A)', 'name_desc'],
['Recently Joined', 'created_at_desc']
]
end
def active_products
self.products.where(paused: false)
end
end`
and my Controller:
`class SuppliersController < ApplicationController
# GET /suppliers
# GET /suppliers.json
def index
@filterrific = Filterrific.new(
Supplier,
params[:filterrific] || session[:filterrific_suppliers]
)
@filterrific.select_options = {
sorted_by: Supplier.options_for_sorted_by,
}
@suppliers = Supplier.filterrific_find(@filterrific).paginate(page: params[:page], per_page: 15)
session[:filterrific_suppliers] = @filterrific.to_hash
end
def reset_filterrific
# Clear session persistence
session[:filterrific_suppliers] = nil
# Redirect back to the index action for default filter settings.
redirect_to :action => :index
end
def search
if params[:query].present?
@suppliers = Supplier.search(params[:query], page: params[:page])
@supplier = @suppliers[0].name == "Inspiration from Real Weddings" ? @suppliers[1] : @suppliers[0]
else
@suppliers = Supplier.all
end
end
def autocomplete
render json: Supplier.search(params[:query], autocomplete: true, limit: 10).map(&:name)
end
def show
@supplier = Supplier.find(params[:id])
@supplier_comment = SupplierComment.new
@supplier_comments = @supplier.supplier_comments.order('created_at DESC')
respond_to do |format|
format.html # show.html.erb
format.json { render json: @supplier }
end
end
end`
When I use the filters individually, it works fine. But after doing a search and then filtering categories, it shows results that the search alone wouldn't show.
I jus copy n paste from your example, but I have an syntax error in this line: }.join(' AND '),
I'm relatively new in ruby on rails. I hope you can help me :)
scope :search_query, lambda { |query|
return nil if query.blank?
terms = query.downcase.split(/\s+/)
terms = terms.map { |e|
(e.gsub('_', '%') + '%').gsub(/%+/, '%')
}
num_or_conds = 2
where(
terms.map { |term|
"(LOWER(students.first_name) LIKE ? OR LOWER(students.last_name) LIKE ?)"
}.join(' AND '),
*terms.map { |e| [e] * num_or_conds }.flatten
)
}
This feature exists but isn't documented anywhere.
Hello
I've got a problem with regexp. What can be the reason?
I am getting an argument error when the search is submitted and can't figure out exactly what's wrong.
Thanks for any help (info and trace below)
ENV INFO:
filterrific version: 1.3.1
rails version: 4.1.4
ruby: 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin12.0]
IN MODEL:
filterrific(
filter_names: [
:name
]
)
CONTROLLER:
class CoursesController < ApplicationController
def index
@filterrific = Filterrific.new(Course, params[:filterrific])
@courses = Course.filterrific_find(@filterrific).page(params[:page])
respond_to do |format|
format.html
format.js
end
end
end
RAILS LOG:
Started GET "/courses/index?utf8=%E2%9C%93&filterrific%5Bname%5D=p&=1411342345879" for 127.0.0.1 at 2014-09-21 16:43:24 -0700
Processing by CoursesController#index as JS
Parameters: {"utf8"=>"✓", "filterrific"=>{"name"=>"p"}, ""=>"1411342345879"}
Club Load (0.1ms) SELECT "clubs".* FROM "clubs" WHERE "clubs"."subdomain" = 'test' LIMIT 1
Tour Load (0.3ms) SELECT "tours".* FROM "tours" WHERE (club_id = 2) AND "tours"."id" = ? ORDER BY "tours"."name" ASC LIMIT 1 [["id", 11]]
STACK TRACE:
ArgumentError - wrong number of arguments (1 for 0):
filterrific (1.3.1) lib/filterrific/active_record_extension.rb:52:in block in filterrific_find' filterrific (1.3.1) lib/filterrific/active_record_extension.rb:49:in
filterrific_find'
app/controllers/courses_controller.rb:7:in index' actionpack (4.1.4) lib/action_controller/metal/implicit_render.rb:4:in
send_action'
actionpack (4.1.4) lib/abstract_controller/base.rb:189:in process_action' actionpack (4.1.4) lib/action_controller/metal/rendering.rb:10:in
process_action'
actionpack (4.1.4) lib/abstract_controller/callbacks.rb:20:in block in process_action' activesupport (4.1.4) lib/active_support/callbacks.rb:113:in
call'
activesupport (4.1.4) lib/active_support/callbacks.rb:229:in block in halting' activesupport (4.1.4) lib/active_support/callbacks.rb:166:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:166:in block in halting' activesupport (4.1.4) lib/active_support/callbacks.rb:229:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:166:in block in halting' activesupport (4.1.4) lib/active_support/callbacks.rb:166:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:299:in block (2 levels) in halting' app/controllers/application_controller.rb:42:in
scope_current_club'
activesupport (4.1.4) lib/active_support/callbacks.rb:424:in block in make_lambda' activesupport (4.1.4) lib/active_support/callbacks.rb:298:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:166:in block in halting' activesupport (4.1.4) lib/active_support/callbacks.rb:166:in
block in halting'
activesupport (4.1.4) lib/active_support/callbacks.rb:86:in run_callbacks' actionpack (4.1.4) lib/abstract_controller/callbacks.rb:19:in
process_action'
actionpack (4.1.4) lib/action_controller/metal/rescue.rb:29:in process_action' actionpack (4.1.4) lib/action_controller/metal/instrumentation.rb:31:in
block in process_action'
activesupport (4.1.4) lib/active_support/notifications.rb:159:in block in instrument' activesupport (4.1.4) lib/active_support/notifications/instrumenter.rb:20:in
instrument'
activesupport (4.1.4) lib/active_support/notifications.rb:159:in instrument' actionpack (4.1.4) lib/action_controller/metal/instrumentation.rb:30:in
process_action'
actionpack (4.1.4) lib/action_controller/metal/params_wrapper.rb:250:in process_action' activerecord (4.1.4) lib/active_record/railties/controller_runtime.rb:18:in
process_action'
actionpack (4.1.4) lib/abstract_controller/base.rb:136:in process' actionview (4.1.4) lib/action_view/rendering.rb:30:in
process'
actionpack (4.1.4) lib/action_controller/metal.rb:196:in dispatch' actionpack (4.1.4) lib/action_controller/metal/rack_delegation.rb:13:in
dispatch'
actionpack (4.1.4) lib/action_controller/metal.rb:232:in block in action' actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:82:in
dispatch'
actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:50:in call' actionpack (4.1.4) lib/action_dispatch/journey/router.rb:71:in
block in call'
actionpack (4.1.4) lib/action_dispatch/journey/router.rb:59:in call' actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:678:in
call'
dragonfly (1.0.5) lib/dragonfly/middleware.rb:14:in call' rack (1.5.2) lib/rack/etag.rb:23:in
call'
rack (1.5.2) lib/rack/conditionalget.rb:25:in call' rack (1.5.2) lib/rack/head.rb:11:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/params_parser.rb:27:in call' actionpack (4.1.4) lib/action_dispatch/middleware/flash.rb:254:in
call'
rack (1.5.2) lib/rack/session/abstract/id.rb:225:in context' rack (1.5.2) lib/rack/session/abstract/id.rb:220:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/cookies.rb:560:in call' activerecord (4.1.4) lib/active_record/query_cache.rb:36:in
call'
activerecord (4.1.4) lib/active_record/connection_adapters/abstract/connection_pool.rb:621:in call' activerecord (4.1.4) lib/active_record/migration.rb:380:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/callbacks.rb:29:in block in call' activesupport (4.1.4) lib/active_support/callbacks.rb:82:in
run_callbacks'
actionpack (4.1.4) lib/action_dispatch/middleware/callbacks.rb:27:in call' actionpack (4.1.4) lib/action_dispatch/middleware/reloader.rb:73:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/remote_ip.rb:76:in call' better_errors (1.1.0) lib/better_errors/middleware.rb:84:in
protected_app_call'
better_errors (1.1.0) lib/better_errors/middleware.rb:79:in better_errors_call' better_errors (1.1.0) lib/better_errors/middleware.rb:56:in
call'
actionpack (4.1.4) lib/action_dispatch/middleware/debug_exceptions.rb:17:in call' actionpack (4.1.4) lib/action_dispatch/middleware/show_exceptions.rb:30:in
call'
railties (4.1.4) lib/rails/rack/logger.rb:38:in call_app' railties (4.1.4) lib/rails/rack/logger.rb:20:in
block in call'
activesupport (4.1.4) lib/active_support/tagged_logging.rb:68:in block in tagged' activesupport (4.1.4) lib/active_support/tagged_logging.rb:26:in
tagged'
activesupport (4.1.4) lib/active_support/tagged_logging.rb:68:in tagged' railties (4.1.4) lib/rails/rack/logger.rb:20:in
call'
request_store (1.0.7) lib/request_store/middleware.rb:8:in call' actionpack (4.1.4) lib/action_dispatch/middleware/request_id.rb:21:in
call'
rack (1.5.2) lib/rack/methodoverride.rb:21:in call' rack (1.5.2) lib/rack/runtime.rb:17:in
call'
activesupport (4.1.4) lib/active_support/cache/strategy/local_cache_middleware.rb:26:in call' dragonfly (1.0.5) lib/dragonfly/cookie_monster.rb:9:in
call'
rack (1.5.2) lib/rack/lock.rb:17:in call' actionpack (4.1.4) lib/action_dispatch/middleware/static.rb:64:in
call'
rack (1.5.2) lib/rack/sendfile.rb:112:in call' railties (4.1.4) lib/rails/engine.rb:514:in
call'
railties (4.1.4) lib/rails/application.rb:144:in call' unicorn (4.8.3) lib/unicorn/http_server.rb:576:in
process_client'
unicorn (4.8.3) lib/unicorn/http_server.rb:670:in worker_loop' unicorn (4.8.3) lib/unicorn/http_server.rb:525:in
spawn_missing_workers'
unicorn (4.8.3) lib/unicorn/http_server.rb:140:in start' unicorn (4.8.3) bin/unicorn_rails:209:in
<top (required)>'
bin/unicorn_rails:16:in <top (required)>' -e:1:in
I need your advice, thank you!
I am trying to use Filterrific with Devise, but getting an undefined method error for filterrific
in the user model.
From the debug log it looks like it's coming from the "directive"
class User < ActiveRecord::Base
filterrific(
:default_settings => { :sorted_by => 'created_at_desc' },
:filter_names => [
:sorted_by,
:search_query,
:with_country_id,
:with_created_at_gte
]
)
I am not sure if what I want to do is even possible with filterific.
I am currently looking into building a single unified search for my website.
This would hit a few different tables with different types of data.
Ideally what I could do is be able to do is have the scopes for each in the their model and then in the controller for the unified search it would be able to do queries against all of the models based on their relevant options and then combine all of the data.
Then in my view I would just check the type of object it is to determine how it displays in the search.
I am not sure if this is possible with filterific, I can't find any examples of this working anywhere else.
Thanks
Im trying to move away from from ransack/meta_search to filterrific. However there is one form helper method I could live without, unfortunately I don't enough time with the source code myself to figure out how to implement it. Im talking the #sort_link method, it basicly allows a user to click on the link and have it sort on the specific named scope.
https://github.com/activerecord-hackery/ransack/blob/master/lib/ransack/helpers/form_helper.rb#L38
def sort_link(search, attribute, *args)
# Extract out a routing proxy for url_for scoping later
if search.is_a?(Array)
routing_proxy = search.shift
search = search.first
end
raise TypeError, "First argument must be a Ransack::Search!" unless
Search === search
search_params = params[search.context.search_key].presence ||
{}.with_indifferent_access
attr_name = attribute.to_s
name = (
if args.size > 0 && !args.first.is_a?(Hash)
args.shift.to_s
else
Translate.attribute(attr_name, :context => search.context)
end
)
if existing_sort = search.sorts.detect { |s| s.name == attr_name }
prev_attr, prev_dir = existing_sort.name, existing_sort.dir
end
options = args.first.is_a?(Hash) ? args.shift.dup : {}
default_order = options.delete :default_order
current_dir = prev_attr == attr_name ? prev_dir : nil
if current_dir
new_dir = current_dir == 'desc' ? 'asc' : 'desc'
else
new_dir = default_order || 'asc'
end
html_options = args.first.is_a?(Hash) ? args.shift.dup : {}
css = ['sort_link', current_dir].compact.join(' ')
html_options[:class] = [css, html_options[:class]].compact.join(' ')
query_hash = {}
query_hash[search.context.search_key] = search_params
.merge(:s => "#{attr_name} #{new_dir}")
options.merge!(query_hash)
options_for_url = params.merge options
url = if routing_proxy && respond_to?(routing_proxy)
send(routing_proxy).url_for(options_for_url)
else
url_for(options_for_url)
end
link_to(
[ERB::Util.h(name), order_indicator_for(current_dir)]
.compact
.join(' ')
.html_safe,
url,
html_options
)
end
This is my offers_controller index method:
def index
filterrific_params = {:with_partner_id => current_partner.id}.deep_merge(params[:filterrific] || session[:filterrific_offers] || {})
@filterrific = Filterrific.new(Offer, filterrific_params)
@offers = Offer.filterrific_find(@filterrific).page(params[:page]).per(10).order('created_at' => :desc)
session[:filterrific_offers] = @filterrific.to_hash
respond_to do |format|
format.html
format.js
end
end
This worked perfect untill I updated filterrific-gem to 2.0.5
If I go back to using 1.4.2 for example, I get:
undefined method
filterrific_filter_names'`
What exactly am I doing wrong?
Thanks!
I followed the exact setup steps in the example and getting the above error message. Any ideas why this might be happening?
Student.rb
belongs_to :user
has_many :assessments
attr_accessor :referer
filterrific(
default_filter_params: { sorted_by: 'created_at_desc' },
available_filters: [
:sorted_by,
:search_query,
:with_created_at_gte
]
)
Student controller:
@patients = current_user.patients.sort_by &:first_name
@filterrific = initialize_filterrific(
Patient,
params[:filterrific]
) or return
@patients = @filterrific.find.page(params[:page])
respond_to do |format|
format.html
format.js
end
end
I have a list of Stories I am displaying. I have added a checkbox to the list filters. When the checkbox is checked, I want to only display the Stories that the current user likes. The checkbox will only pass whether it is checked or not. The controller knows the current_user but the model, where the scopes are defined, does not. Is there a way to add it into the @filterrific object from the controller so the scope has access to the current_user? Is there an easier way to do this that I am just missing? I'm still kind of new to Rails. Thanks!
Hi there - love your gem! I would like to use it with a db with about 100k entires, however I would like for all those entries to not auto-populate as soon as the index.html.erb page is loaded; only after a user has entered their search/sort criteria, and if the filters are reset the results would again clear.
I've tried playing with the controller code in an attempt to prevent @inst_var = @filterrific.find.page(params[:page])
from populating right away, but have only succeeded in breaking the code over and again. Any advice is welcomed. Thanks!
I'm new in the use of filterrific.
In my application I got the error in the subject.
I'm using
filterrific (2.0.5)
rails (4.2.1)
ruby 1.9.3 p545 on win7
STACK TRACE:
activerecord (4.2.1) lib/active_record/dynamic_matchers.rb:26:in method_missing' app/controllers/prevheads_controller.rb:9:in
index'
actionpack (4.2.1) lib/action_controller/metal/implicit_render.rb:4:in send_action' actionpack (4.2.1) lib/abstract_controller/base.rb:198:in
process_action'
actionpack (4.2.1) lib/action_controller/metal/rendering.rb:10:in process_action' actionpack (4.2.1) lib/abstract_controller/callbacks.rb:20:in
block in process_action'
activesupport (4.2.1) lib/active_support/callbacks.rb:117:in call' activesupport (4.2.1) lib/active_support/callbacks.rb:117:in
call'
activesupport (4.2.1) lib/active_support/callbacks.rb:555:in block (2 levels) in compile' activesupport (4.2.1) lib/active_support/callbacks.rb:505:in
call'
activesupport (4.2.1) lib/active_support/callbacks.rb:505:in call' activesupport (4.2.1) lib/active_support/callbacks.rb:92:in
_run_callbacks'
activesupport (4.2.1) lib/active_support/callbacks.rb:776:in _run_process_action_callbacks' activesupport (4.2.1) lib/active_support/callbacks.rb:81:in
run_callbacks'
actionpack (4.2.1) lib/abstract_controller/callbacks.rb:19:in process_action' actionpack (4.2.1) lib/action_controller/metal/rescue.rb:29:in
process_action'
actionpack (4.2.1) lib/action_controller/metal/instrumentation.rb:32:in block in process_action' activesupport (4.2.1) lib/active_support/notifications.rb:164:in
block in instrument'
activesupport (4.2.1) lib/active_support/notifications/instrumenter.rb:20:in instrument' activesupport (4.2.1) lib/active_support/notifications.rb:164:in
instrument'
actionpack (4.2.1) lib/action_controller/metal/instrumentation.rb:30:in process_action' actionpack (4.2.1) lib/action_controller/metal/params_wrapper.rb:250:in
process_action'
activerecord (4.2.1) lib/active_record/railties/controller_runtime.rb:18:in process_action' actionpack (4.2.1) lib/abstract_controller/base.rb:137:in
process'
actionview (4.2.1) lib/action_view/rendering.rb:30:in process' actionpack (4.2.1) lib/action_controller/metal.rb:196:in
dispatch'
actionpack (4.2.1) lib/action_controller/metal/rack_delegation.rb:13:in dispatch' actionpack (4.2.1) lib/action_controller/metal.rb:237:in
block in action'
actionpack (4.2.1) lib/action_dispatch/routing/route_set.rb:74:in call' actionpack (4.2.1) lib/action_dispatch/routing/route_set.rb:74:in
dispatch'
actionpack (4.2.1) lib/action_dispatch/routing/route_set.rb:43:in serve' actionpack (4.2.1) lib/action_dispatch/journey/router.rb:43:in
block in serve'
actionpack (4.2.1) lib/action_dispatch/journey/router.rb:30:in each' actionpack (4.2.1) lib/action_dispatch/journey/router.rb:30:in
serve'
actionpack (4.2.1) lib/action_dispatch/routing/route_set.rb:819:in call' rack (1.6.1) lib/rack/etag.rb:24:in
call'
rack (1.6.1) lib/rack/conditionalget.rb:25:in call' rack (1.6.1) lib/rack/head.rb:13:in
call'
actionpack (4.2.1) lib/action_dispatch/middleware/params_parser.rb:27:in call' actionpack (4.2.1) lib/action_dispatch/middleware/flash.rb:260:in
call'
rack (1.6.1) lib/rack/session/abstract/id.rb:225:in context' rack (1.6.1) lib/rack/session/abstract/id.rb:220:in
call'
actionpack (4.2.1) lib/action_dispatch/middleware/cookies.rb:560:in call' activerecord (4.2.1) lib/active_record/query_cache.rb:36:in
call'
activerecord (4.2.1) lib/active_record/connection_adapters/abstract/connection_pool.rb:649:in call' activerecord (4.2.1) lib/active_record/migration.rb:378:in
call'
actionpack (4.2.1) lib/action_dispatch/middleware/callbacks.rb:29:in block in call' activesupport (4.2.1) lib/active_support/callbacks.rb:88:in
call'
activesupport (4.2.1) lib/active_support/callbacks.rb:88:in _run_callbacks' activesupport (4.2.1) lib/active_support/callbacks.rb:776:in
_run_call_callbacks'
activesupport (4.2.1) lib/active_support/callbacks.rb:81:in run_callbacks' actionpack (4.2.1) lib/action_dispatch/middleware/callbacks.rb:27:in
call'
actionpack (4.2.1) lib/action_dispatch/middleware/reloader.rb:73:in call' actionpack (4.2.1) lib/action_dispatch/middleware/remote_ip.rb:78:in
call'
actionpack (4.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:17:in call' web-console (2.1.2) lib/web_console/middleware.rb:37:in
call'
actionpack (4.2.1) lib/action_dispatch/middleware/show_exceptions.rb:30:in call' railties (4.2.1) lib/rails/rack/logger.rb:38:in
call_app'
railties (4.2.1) lib/rails/rack/logger.rb:20:in block in call' activesupport (4.2.1) lib/active_support/tagged_logging.rb:68:in
block in tagged'
activesupport (4.2.1) lib/active_support/tagged_logging.rb:26:in tagged' activesupport (4.2.1) lib/active_support/tagged_logging.rb:68:in
tagged'
railties (4.2.1) lib/rails/rack/logger.rb:20:in call' actionpack (4.2.1) lib/action_dispatch/middleware/request_id.rb:21:in
call'
rack (1.6.1) lib/rack/methodoverride.rb:22:in call' rack (1.6.1) lib/rack/runtime.rb:18:in
call'
activesupport (4.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in call' rack (1.6.1) lib/rack/lock.rb:17:in
call'
actionpack (4.2.1) lib/action_dispatch/middleware/static.rb:113:in call' rack (1.6.1) lib/rack/sendfile.rb:113:in
call'
railties (4.2.1) lib/rails/engine.rb:518:in call' railties (4.2.1) lib/rails/application.rb:164:in
call'
rack (1.6.1) lib/rack/lock.rb:17:in call' rack (1.6.1) lib/rack/content_length.rb:15:in
call'
rack (1.6.1) lib/rack/handler/webrick.rb:89:in service' C:/Ruby193/lib/ruby/1.9.1/webrick/httpserver.rb:138:in
service'
C:/Ruby193/lib/ruby/1.9.1/webrick/httpserver.rb:94:in run' C:/Ruby193/lib/ruby/1.9.1/webrick/server.rb:191:in
block in start_thread'
Request
Parameters:
None
Toggle session dump
Toggle env dump
Response
Headers:
None
MODEL:
class Prevhead < ActiveRecord::Base
belongs_to :client
belongs_to :carto
belongs_to :costoli
belongs_to :onda
belongs_to :fusto
belongs_to :inco
belongs_to :confe
belongs_to :resa
belongs_to :costoli2
filterrific(
available_filters: [
:with_client_id,
:with_articolo
]
)
scope :with_client_id, lambda { |client_ids|
where(client_id: [*client_ids])
}
scope :with_articolo, lambda { order('articolo ASC') }
validates :client_id, :inclusion => {:in => 2..1000, :message => "Cliente non selezionato"}
validates :articolo, presence: {message: "Articolo non definito"}
validates :descrizione, presence: {message: "Descrizione non inserita"}
validates_numericality_of :qta, message: "Quantita non definita", on: :create
validates_numericality_of :qta, message: "Quantita non definita", on: :edit
validates_numericality_of :scarto, message: "Scarto non definito", on: :create
validates_numericality_of :scarto, message: "Scarto non definito", on: :edit
validates_numericality_of :dim1, message: "Altezza non definita", on: :create
validates_numericality_of :dim1, message: "Altezza non definita", on: :edit
validates_numericality_of :dim2, message: "Larghezza non definita", on: :create
validates_numericality_of :dim2, message: "Larghezza non definita", on: :edit
validates :carto_id, :inclusion => {:in => 2..1000, :message => "Cartoncino non selezionato"}
validates :resa_id, :inclusion => {:in => 2..1000, :message => "Resa non selezionata"}
validates :costoli_id, :inclusion => {:in => 2..1000, :message => "Linea non selezionata"}
end
CONTROLLER:
class PrevheadsController < ApplicationController
def index
@filterrific = initialize_filterrific(
Prevhead,
params[:filterrific],
select_options: {
with_client_id: Client.options_for_select,
},
persistence_id: 'shared_key',
default_filter_params: {},
available_filters: [],
) or return
@prevheads = @filterrific.find.paginate(:page => params[:page], :per_page => 12).order("num DESC","vers DESC").joins(:client)
respond_to do |format|
format.html
format.js
end
end
def show
@prevhead = Prevhead.find(params[:id])
end
def new
@prevhead = Prevhead.new
end
def edit
@prevhead = Prevhead.joins(:client, :carto, :costoli, :fusto, :inco, :confe, :resa).find(params[:id])
end
private
def prevhead_params
params.require(:prevhead).permit(:num, :vers, :client_id, :qta, :articolo, :descrizione, :qta, :scarto, :dim1, :dim2, :formatoc, :carto_id, :resa_id, :costoli_id, :costoli2_id, :onda_id, :fusto_id, :inco_id, :confe_id, :traspo, :data_elab, :co_carto, :co_stampa, :co_avvsta, :co_stampa2, :co_avvsta2, :co_onda, :co_fusto, :co_avvfust, :co_inco, :co_avvinco, :co_confe, :preventivo, :prevtraspo, :un_peso, :un_costo, :un_stampa, :un_stampa2, :un_coston, :un_costof, :un_costoi, :un_sovrap, :un_confe, :un_contenuto, :note, :desclinea2, :descform2, :descolor2, :descdiff2)
end
end
INDEX.HTML.ERB
<%= notice %>
<%= form_for_filterrific @filterrific do |f| %>
<%= render(
partial: 'zzz/elenco',
locals: { prevheads: @prevheads}
) %>
PARTIAL zzz/_elenco
<%= notice %>
<% @page_title="Preventivi" %>
<% @prevheads.each do |prevhead| %> <td><%= button_to 'Mostra', prevhead_path(prevhead), method: :show %></td>
<td><%= button_to 'Copia', copia_path(prevhead), method: :copia %></td>
<td><%= link_to 'Stampa', stampa_path(prevhead), method: :stampa, target: :_blank %></td>
</tr>
<% end %>
Numero |
Versione |
Cliente |
Articolo |
Descrizione |
Quantità |
Preventivo |
Unitario |
Trasporto |
Unit Tot |
Data |
<%= prevhead.num %> | <%= prevhead.vers %> | <%= prevhead.client.ragsoc %> | <%= prevhead.articolo %> | <%= prevhead.descrizione %> | <%= number_with_auto_precision(prevhead.qta, :separator => ',', :delimiter => '.') %> | <%= number_to_currency(prevhead.preventivo, :unit=>'€') %> | <%= number_to_currency(prevhead.preventivo/prevhead.qta, :unit=>'€', :precision =>3) %> | <%= number_to_currency(prevhead.traspo, :unit=>'€') %> | <%= number_to_currency(prevhead.prevtraspo/prevhead.qta, :unit=>'€', :precision =>3) %> | <%= prevhead.data_elab %> |
<%= will_paginate @prevheads %>
TABLE prevheads
create_table "prevheads", force: :cascade do |t|
t.integer "num", limit: 4, null: false
t.integer "vers", limit: 4, null: false
t.integer "client_id", limit: 4, null: false
t.string "articolo", limit: 100, null: false
t.string "descrizione", limit: 200, null: false
t.decimal "qta", precision: 10, scale: 2, null: false
t.decimal "scarto", precision: 10, scale: 3, null: false
t.decimal "dim1", precision: 10, scale: 3, null: false
t.decimal "dim2", precision: 10, scale: 3, null: false
t.string "formatoc", limit: 100, null: false
t.integer "carto_id", limit: 4, null: false
t.integer "resa_id", limit: 4, null: false
t.integer "costoli_id", limit: 4, null: false
t.integer "costoli2_id", limit: 4, null: false
t.integer "onda_id", limit: 4, default: 1, null: false
t.integer "fusto_id", limit: 4, default: 1, null: false
t.integer "inco_id", limit: 4, default: 1, null: false
t.integer "confe_id", limit: 4, default: 1, null: false
t.decimal "traspo", precision: 10, scale: 3, default: 0.0, null: false
t.date "data_elab"
t.decimal "co_carto", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "co_stampa", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "co_avvsta", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "co_stampa2", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "co_avvsta2", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "co_onda", precision: 10, scale: 3, default: 0.0
t.decimal "co_fusto", precision: 10, scale: 3, default: 0.0
t.decimal "co_avvfust", precision: 10, scale: 3, default: 0.0
t.decimal "co_inco", precision: 10, scale: 3, default: 0.0
t.decimal "co_avvinco", precision: 10, scale: 3, default: 0.0
t.decimal "co_confe", precision: 10, scale: 3, default: 0.0
t.decimal "preventivo", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "prevtraspo", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "un_peso", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "un_costo", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "un_stampa", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "un_stampa2", precision: 10, scale: 3, default: 0.0, null: false
t.decimal "un_coston", precision: 10, scale: 3, default: 0.0
t.decimal "un_costof", precision: 10, scale: 3, default: 0.0
t.decimal "un_costoi", precision: 10, scale: 3, default: 0.0
t.decimal "un_sovrap", precision: 10, scale: 3, default: 0.0
t.decimal "un_confe", precision: 10, scale: 3, default: 0.0
t.decimal "un_contenuto", precision: 10, scale: 3, default: 0.0
t.string "note", limit: 255
t.string "desclinea2", limit: 50
t.string "descform2", limit: 50
t.string "descolor2", limit: 50
t.string "descdiff2", limit: 50
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Thank you for any suggestions ...
I have posted a question on stackoverflow about this:
http://stackoverflow.com/questions/27490930/rails-filterrific-with-multiple-parameters
In summary, I have a requirement to filter by two fields that require each others knowledge (zipcode and miles - IE filter by X miles of zipcode Y). But I am not sure how this could be done with filterrific since it only works with single-param scopes.
Kind of linked to the following issue #34
When the params hash is conditioned in ParamSet
, the string that "looks like" a negative number are not casted into negative int.
ex:
[1] > condition_filterrific_params { 'filter_negative_int' => '-42' }
=> { 'filter_negative_int' => '-42' }
# shouldn't this be { 'filter_negative_int' => -42 } ?
Does it make sense to cast as a negative int?
Hi, I have two questions about the gem. First question is, i have a model Post and a model Comment. Post stands in a has_many relationship to Comment. Post should order by count of Comment. I would not use counter cache for this. How should my scope be?
The second question is, i have for my Post model a twitter counter method for count the Tweets. Usually I was to do it like:
Posts.sort_by{ |x| x.twitter_counter }
But unfortunately it does not work, so since it is an array. How can i solve this with a scope ?
Thanks
My issue is fairly simple, in my app I have this scope that retrieves all the courses within a certain distance with the help of a postgis database:
scope :with_distance, -> (lat, lng, distance_in_meters) {...}
The scope is working but I don't know how to write the select options for a scope that has more than one argument. I wrote this huge mess that's not even working (wrong number of arguments) but you get the idea:
[ [['2 km'], [current_user.lat, current_user.lng, 2000]], [['5 km'], [current_user.lat, current_user.lng, 5000]] ]
I've been trying to solve this for a long time, any suggestion would be greatly appreciated
How do I do cascading dropdown in Filterrific
give that i have Domain -> Sector -> Subsector
I tried to initialize the select_options for Sector and Subsector to an empty set and then provide it with value once Domain has been selected.
However in my model when I try to access
filterrific :select_options => { :with_sector_id => Sector.options_for_select }
I get an error "wrong number of arguments (0 for 1)"
See example below.
class Profile < ActiveRecord::Base
filterrific :default_filter_params => { :sorted_by => 'created_at_desc' },
:available_filters => %w[
with_domain_id
with_sector_id
with_subsector_id
]
scope :with_domain_id, lambda { |with_domain_id|
# select and search for the content.
profile_expertises = Expertise.arel_table
profile_searches = Profile.arel_table
where(
Expertise \
.where(profile_expertises[:profile_id].eq(profile_searches[:id] )) \
.where(profile_expertises[:domain_id].in([*with_domain_id].map(&:to_i))) \
.exists
)
filterrific :select_options => { :with_sector_id => Sector.options_for_select }
class SearchesController < ApplicationController
def index
@filterrific = initialize_filterrific(
Profile,
params[:filterrific],
:select_options => {
sorted_by: Profile.options_for_sorted_by,
with_domain_id: Domain.options_for_select,
with_sector_id: [],
with_subsector_id: [],
}
)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.