jhund / filterrific

Filterrific is a Rails Engine plugin that makes it easy to filter, search, and sort your ActiveRecord lists.
http://filterrific.clearcove.ca
MIT License
910 stars 124 forks source link

Parameters not being evaluated on load #93

Closed Reveren closed 8 years ago

Reveren commented 8 years ago

Like the title says, I can't seem to make this work with my setup. I get no errors. When choosing an option from a select list, everything seems to go OK, along with all the AJAX, but the filter is not actually applied to the results. For instance I have a model Recipe that includes a type_id that I am filtering from. I can choose the results and from the WEBrick output the parameter gets the value, but the load doesn't have the parameters in its syntax.

Recipe model

class Recipe < ActiveRecord::Base
  filterrific(
    default_filter_params: { sorted_by: 'created_at_desc' },
    available_filters: [
      :sorted_by,
      :search_query,
      :with_type_id
    ]
  )

  belongs_to :type

  scope :sorted_by, lambda { |sort_option|
    order("created_at DESC")
  }

  scope :with_type_id, lambda { |type_ids|
    where(type_id: [*type_ids])
  }

  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(recipes.title) LIKE ?)"
      }.join(' AND '),
      *terms.map { |e| [e] * num_or_conds }.flatten
    )
  }

  def self.options_for_sorted_by
    [
      ['Name (a-z)', 'title_asc'],
      ['Created date (newest first)', 'created_at_desc'],
      ['Created date (oldest first)', 'created_at_asc']
    ]
  end
end

Type model

class Type < ActiveRecord::Base
  has_many :recipes
  def self.options_for_select
    order('LOWER(title)').map { |e| [e.title, e.id] }
  end
end

Recipes controller

class RecipesController < ApplicationController
  def index
    @filterrific = initialize_filterrific(
      Recipe,
      params[:filterrific],
      select_options: {
        sorted_by: Recipe.options_for_sorted_by,
        with_type_id: Type.options_for_select
      },
      persistence_id: 'shared_key',
      default_filter_params: {},
      available_filters: [],
    ) or return
    @recipes = @filterrific.find.page(params[:page])

    respond_to do |format|
      format.html
      format.js
    end

  rescue ActiveRecord::RecordNotFound => e
    puts "Had to reset filterrific params: #{ e.message }"
    redirect_to(reset_filterrific_url(format: :html)) and return
  end
end

views/recipe/index.html.erb

<%= form_for_filterrific @filterrific, html: { class: "form-horizontal" }  do |f| %>
  <div class="form-group">
    Type
    <%= f.select(:with_type_id, @filterrific.select_options[:with_type_id], { include_hidden: false, include_blank: '- Any -' }) %>
  </div>
  <div class="card-block">
    <%= page_entries_info @recipes %>
    <%= render_filterrific_spinner %>
    <%= link_to 'Reset filters', reset_filterrific_url %>
  </div>
<% end %>
<%= render( partial: 'recipes/list', locals: { recipes: @recipes } ) %>

_list.html.erb

<div id="filterrific_results">
  <% @recipes.each_slice(3) do |recipes| %>
    <div class="row">
      <% recipes.each do |recipe| %>
        <div class="col-md-4">
          <div class="recipe">
            <div class="image_wrapper">
              <%= link_to recipe do %>
                <%= image_tag recipe.image.url(:medium) %>
              <% end %>
             </div>
             <h2><%= link_to recipe.title, recipe %></h2>
             <p>Submitted by <%= recipe.user.username %></p>
           </div>
         </div>
       <% end %>
    </div>
  <% end %>
</div>

index.js.erb

<% js = escape_javascript(
  render(partial: 'recipes/list', locals: { recipes: @recipes })
) %>
$("#filterrific_results").html("<%= js %>");

Here is the output of my WEBrick when I click an option:

  ActiveRecord::SchemaMigration Load (0.3ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by RecipesController#index as JS
  Parameters: {"utf8"=>"✓", "filterrific"=>{"with_type_id"=>"1"}, "_"=>"1463779206346"}
  Type Load (0.3ms)  SELECT "types".* FROM "types"  ORDER BY LOWER(title)
  Recipe Load (0.4ms)  SELECT  "recipes".* FROM "recipes"  ORDER BY created_at DESC LIMIT 30 OFFSET 0
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
  CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
  Rendered recipes/_list.html.erb (46.8ms)
  Rendered recipes/index.js.erb (56.7ms)
Completed 200 OK in 139ms (Views: 82.1ms | ActiveRecord: 1.8ms)

As you can see, the Parameters line gets the with_type_id => 1 but it is not carried over to the Recipe Load query. This is pretty much taken right from the website, where Students become Recipes and Country becomes Type. Am I missing something or have I just hosed it up altogether?

edit: Ruby - 2.3.0 Rails - 4.2.6 Filterrific - 2.0.5

blaedj commented 8 years ago

Try removing the available_filters: [] in your recipes controller when initializing the filterrific variable. It overrides the available_filters specified in your model, and since the filter is empty you are removing all the filters that can be applied for that instance of filterrific.

Reveren commented 8 years ago

That did it. It now works like a champ. Thanks.