How to make an ActiveRecord request to get an item common to several other items

103 Views Asked by At

I am trying to modify Sharetribe, a Ruby on Rails framework for online communities. There is this method that returns me relevant search filters.

For now, it returns me a filter if it is present in any one of the categories (identified by category_ids ) .

I would like it to return a filter if and only if it is present in ALL of the categories identified by category_ids.

Being new to Rails and ActiveRecord, I'm a bit lost. Here is the method returning relevant filters :

 # Database select for "relevant" filters based on the `category_ids`
  #
  # If `category_ids` is present, returns only filter that belong to
  # one of the given categories. Otherwise returns all filters.
  #
  def select_relevant_filters(category_ids)
    relevant_filters =
      if category_ids.present?
        @current_community
          .custom_fields
          .joins(:category_custom_fields)
          .where("category_custom_fields.category_id": category_ids, search_filter: true)
          .distinct
      else
        @current_community
          .custom_fields.where(search_filter: true)
      end

    relevant_filters.sort
  end

Is there a way to change the SQL request, or should I retrieve all the fields as it is doing right now and then delete the ones I am not interested in ?

2

There are 2 best solutions below

0
On BEST ANSWER

So I solved my problem by selecting filters that are pesent in all of the subcategories of the selected category. For that I select all filters of all subcategory, and only keep the ones that are returned a number of times exactly equal to the number of subcategory.

  all_relevant_filters = select_relevant_filters(m_selected_category.own_and_subcategory_ids.or_nil)

  nb_sub_category = m_selected_category.subcategory_ids.size
  if nb_sub_category.none?
    relevant_filters = all_relevant_filters
  else
    relevant_filters = all_relevant_filters.select{ |e| all_relevant_filters.count(e) == nb_sub_category.get }.uniq
  end
3
On

Try the following

  def select_relevant_filters_if_all(category_ids)
    relevant_filters =
    if category_ids.present?
      @current_community
        .custom_fields
        .joins(:category_custom_fields)
        .where("category_custom_fields.category_id": category_ids, search_filter: true)
        .group("category_custom_fields.id") 
        .having("count(category_custom_fields.id)=?", category_ids.count)
        .distinct
    else
      @current_community
        .custom_fields.where(search_filter: true)
    end

    relevant_filters.sort
  end

This is a new method in your HomeController, pay attention the name is different, just to omit monkeypatching. Comments are welcome.