搜索功能rails 4

时间:2016-07-28 09:21:44

标签: ruby-on-rails ruby ruby-on-rails-4

我有一个当前的实现,允许我按类别名称

过滤我的搜索结果
class Category < ActiveRecord::Base
  has_many :bike_categories
  has_many :bikes, through: :bike_categories
end

class BikeCategory < ActiveRecord::Base
   # Holds bike_id and category_id to allow multiple categories to be saved per image, as opposed to storing an array of objects in one DB column
  belongs_to :bike
  belongs_to :category
end

class Bike < ActiveRecord::Base
  has_many :bike_categories, dependent: :destroy
  has_many :categories, through: :bike_categories
end

Model

def self.search(params)
  includes_categories(params[:name])
end

def self.includes_categories(category_names)
  joins(:categories)
  .where(categories: { name: category_names })
  .group('bikes.id')
  .having("count(*) = ?", category_names.size)
end

所以,如果我有以下数据

Bike
id: 1 title: 'Bike 1'
id: 2 title: 'Bike 2'

category
id: 1 name: 'Mens'
id: 2 name: 'Womens'
id: 3 name: 'Mountain Bike'
id: 4 name: 'Hybrid'

bike_categories
id: 1 bike_id: 1 :category_id: 2 # Womens, Mountain Bike
id: 2 bike_id: 1 :category_id: 3 

id: 3 bike_id: 2 :category_id: 2 # Womens, Hybrid
id: 4 bike_id: 2 :category_id: 4

在我的过滤条件中,如果我选择WomensMountain Bikes,我会获得所有类别为Womens, Mountain Bikes的自行车,因此在此示例中仅显示一个结果。

然而,我希望更进一步,选择另一个类别,hybrid(所以我会选择过滤器Womens, Mountain Bikes, Hybrid),并希望所有自行车都有Womens, Mountain Bikes和{ {1}},所以在这个例子中我应该得到2个结果返回

我如何修改此查询以允许此操作?

由于

1 个答案:

答案 0 :(得分:0)

我使用了以下几行中的内容来允许按多个属性过滤搜索结果

# style for Mountian Bike etc.
class Style < ActiveRecord::Base
  has_many :bike_styles
  has_many :bikes, through: :bike_styles
end

class BikeStyle < ActiveRecord::Base
  belongs_to :bike
  belongs_to :style
end

# gender for Womens, Mens etc. 
# (or maybe there is a better name if you have girls / boys as well)
class Gender < ActiveRecord::Base
  has_many :bike_genders
  has_many :bikes, through: :bike_genders
end

class BikeGender < ActiveRecord::Base
  belongs_to :bike
  belongs_to :gender
end

class Bike < ActiveRecord::Base
  has_many :bike_styles, dependent: :destroy
  has_many :styles, through: :bike_styles

  has_many :bike_genders, dependent: :destroy
  has_many :genders, through: :bike_genders

  # repeat for other searchable attributes ( e.g. frame size )
  # has_many :bike_sizes, dependent: :destroy
  # has_many :sizes, through: :bike_sizes

  # returns filtered results based on the params, call as follows:
  #   Bikes.search style: "Mountian Bike", gender: "Mens"    
  #   Bikes.search style: "Mountian Bike"
  #   Bikes.search gender: "Mens"
  def self.search(params)
    filtered = params[:collection] || self
    filtered = style_filter(filtered, params[:style])
    filtered = gender_filter(filtered, params[:gender])
    filtered
  end

  # filters by style (if one is provided)  
  def self.style_filter(filtered, style)
     filtered = filtered.joins(:styles).where(styles: {name: style}) unless style.blank?
     filtered
   end

  # filters by gender (if one is provided)  
  def self.gender_filter(filtered, gender)
     filtered = filtered.joins(:genders).where(genders: {name: gender}) unless gender.blank?
     filtered
   end
end