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

Many to many returns undefined method `exists' #215

Open marvinick opened 1 year ago

marvinick commented 1 year ago

Hi @jhund

ruby 3.1.2 rails 7.0.1 filterrific (5.2.2)

I'm trying to filter companies with the selected category. I have the following many-to-many relationship between Company and Category.

company.rb

has_many :company_categories has_many :categories, through: :company_categories

scope :with_any_category_ids, ->(category_ids) {
    # get a reference to the join table
    company_categories = CompanyCategory.arel_table
    # get a reference to the filtered table
    companies = Company.arel_table
    # let AREL generate a complex SQL query
    where(
      CompanyCategory
        .where(company_categories[:company_id].eq(companies[:id]))
        .where(company_categories[:category_id].in([*category_ids].map(&:to_i)))
        .exists,
    )
}

category.rb

has_many :company_categories has_many :companies, through: :company_categories

company_category.rb

class CompanyCategory < ApplicationRecord
  belongs_to :company
  belongs_to :category
end

companies/index.html.erb

<%= f.select :with_any_category_ids, @filterrific.select_options[:with_any_category_ids], { :include_blank => 'categories' }, { :class => 'form-control' } %>

companies_controllers.rb

def index

    @categories = @country.categories.pluck(:name)
    (@filterrific = initialize_filterrific(
      @country.companies, 
      params[:filterrific],
      select_options: { 
        with_any_state_ids: State.where(country_id: @country.id).options_for_select,
        with_any_category_ids: @country.categories.options_for_select
      },
      persistence_id: false,
    )) || return

    @companies = @filterrific.find.page(params[:page])
    @pagy, @companies = pagy(@filterrific.find.page(params[:page]), items: 24)

end

I keep getting _undefined method `exists' whenever I try to filter companies with the selected category

Started GET "/countries/usa/companies?filterrific%5Bwith_any_state_ids%5D=&filterrific%5Bwith_any_category_ids%5D=5&filterrific%5Bwith_year_founded%5D=&filterrific%5Bwith_charity%5D=0&filterrific%5Bwith_sustainable%5D=0&filterrific%5Bwith_lifetime_warranty%5D=0&filterrific%5Bwith_public%5D=0&filterrific%5Bwith_job%5D=0&filterrific%5Bwith_manufacturer_location%5D=0&filterrific%5Bwith_veteran_owned%5D=0&filterrific%5Bwith_woman_owned%5D=0&filterrific%5Bwith_minority_owned%5D=0&filterrific%5Bwith_family_owned%5D=0&filterrific%5Bwith_affiliate%5D=0&filterrific%5Bwith_discount%5D=0&filterrific%5Bwith_religious%5D=0&filterrific%5Bwith_employee_owned%5D=0&filterrific%5Bwith_lgbt_owned%5D=0&filterrific%5Bwith_brand_ambassador%5D=0&filterrific%5Bwith_reseller%5D=0&filterrific%5Bwith_diversity%5D=0&commit=Show%20results" for ::1 at 2022-11-08 10:19:57 -0600
Processing by CompaniesController#index as JS
  Parameters: {"filterrific"=>{"with_any_state_ids"=>"", "with_any_category_ids"=>"5", "with_year_founded"=>"", "with_charity"=>"0", "with_sustainable"=>"0", "with_lifetime_warranty"=>"0", "with_public"=>"0", "with_job"=>"0", "with_manufacturer_location"=>"0", "with_veteran_owned"=>"0", "with_woman_owned"=>"0", "with_minority_owned"=>"0", "with_family_owned"=>"0", "with_affiliate"=>"0", "with_discount"=>"0", "with_religious"=>"0", "with_employee_owned"=>"0", "with_lgbt_owned"=>"0", "with_brand_ambassador"=>"0", "with_reseller"=>"0", "with_diversity"=>"0"}, "commit"=>"Show results", "country_id"=>"usa"}
  Country Load (1.1ms)  SELECT "countries".* FROM "countries" WHERE "countries"."slug" = $1 LIMIT $2  [["slug", "usa"], ["LIMIT", 1]]
  ↳ app/controllers/companies_controller.rb:173:in `set_country'
  Category Pluck (0.2ms)  SELECT "categories"."name" FROM "categories" WHERE "categories"."country_id" = $1  [["country_id", 16]]
  ↳ app/controllers/companies_controller.rb:14:in `index'
  State Pluck (0.5ms)  SELECT "states"."name", "states"."id" FROM "states" WHERE "states"."country_id" = $1 ORDER BY LOWER("states"."name")  [["country_id", 16]]
  ↳ app/models/state.rb:17:in `options_for_select'
  Category Pluck (0.3ms)  SELECT "categories"."name", "categories"."id" FROM "categories" WHERE "categories"."country_id" = $1 ORDER BY LOWER("categories"."name")  [["country_id", 16]]
  ↳ app/models/category.rb:13:in `options_for_select'
  CompanyCategory Load (1.0ms)  SELECT "company_categories".* FROM "company_categories" WHERE "company_categories"."company_id" = "companies"."id" AND "company_categories"."category_id" IN (5) /* loading for inspect */ LIMIT $1  [["LIMIT", 11]]
  ↳ lib/cloudflare_proxy.rb:11:in `call'
Completed 500 Internal Server Error in 16ms (ActiveRecord: 2.1ms | Allocations: 10438)

  CompanyCategory Load (0.4ms)  SELECT "company_categories".* FROM "company_categories" WHERE "company_categories"."company_id" = "companies"."id" AND "company_categories"."category_id" IN (5) /* loading for inspect */ LIMIT $1  [["LIMIT", 11]]

NoMethodError (undefined method `exists' for #<CompanyCategory::ActiveRecord_Relation:0x000000010b84b0a0>
Did you mean?  exists?):

app/models/company.rb:104:in `block in <class:Company>'
app/controllers/companies_controller.rb:26:in `index'
lib/cloudflare_proxy.rb:11:in `call'

I have no problem with other scopes: Filter by column values, Filter by ranges etc. except this one (Filter by existence of many-to-many association)

And I follow everything here http://filterrific.clearcove.ca/pages/active_record_scope_patterns.html to the T.

marvinick commented 1 year ago

I'm not sure if this is related to https://github.com/jhund/filterrific/issues/71