Rails如何使用连接表和条件编写查询

时间:2019-01-09 14:02:39

标签: ruby-on-rails

我有两个表,类别产品

  create_table "categories", force: :cascade do |t|
    t.string "title", limit: 100, null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "products", force: :cascade do |t|
    t.string "title", limit: 150, null: false
    t.decimal "price", precision: 15, scale: 2, default: "0.0", null: false
    t.text "description"
    t.bigint "category_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "color"
    t.integer "user_id"
    t.json "attachments"
    t.index ["category_id"], name: "index_products_on_category_id"
  end

在我的搜索表中,用户可以输入与以下任何一个匹配的关键字:

  • 产品标题
  • 产品颜色
  • 产品说明
  • 产品颜色

也应按产品的类别标题查找。

在我的产品控制器中,我有该方法:

def filter_products
  return if params[:query].blank?
  @products = Product.joins(:category).where('lower(categories.title) LIKE ?', "%#{params[:query][:keyword]}%")
  @products = Product.where('lower(title) LIKE ?', "%#{params[:query][:keyword]}%")
      .or(Product.where('lower(description) LIKE ?', "%#{params[:query][:keyword]}%"))
      .or(Product.where('lower(color) LIKE ?', "%#{params[:query][:keyword]}%"))
end

当我按产品类别搜索产品时,它什么也不会返回

如果删除此行,它将返回预期的结果:

 @products = Product.where('lower(title) LIKE ?', "%#{params[:query][:keyword]}%")
    .or(Product.where('lower(description) LIKE ?', "%#{params[:query][:keyword]}%"))
    .or(Product.where('lower(color) LIKE ?', "%#{params[:query][:keyword]}%"))

因为不可能在查询中使用 joins ...

如何更改我的方法以按产品类别标题或按产品(标题,描述,颜色)返回?

1 个答案:

答案 0 :(得分:0)

根据您的代码,第二条查询行覆盖@products变量。

即使您不重写@products变量,在这种情况下,Rails也会在您的第一和第二查询行之间放置一个“和” SQL运算符。一种更清晰的方法是编写原始SQL where子句与“或”运算符连接

代码将是

cols = ["`categories`.`title` LIKE :query","`products`.`title` LIKE :query", "`products`.`description` LIKE :query", "`products`.`position` LIKE :query"]

@products = Product.joins(:category).where(cols.join(" OR "), query: "%#{{params[:query][:keyword]}%")

这更加清晰,代码更少。