Rails 5自定义查询使用where.not in并且属于许多关联

时间:2018-03-18 22:31:20

标签: ruby-on-rails ruby-on-rails-5

我的product模型与has_and_belongs_to_manytags关联。我正在尝试创建自定义查询以排除具有特定标记的某些产品。使用下面的代码,我收到错误PG::UndefinedColumn: ERROR: column products.product_id does not exist...如果我从.where.not(products_tags: 'Mouldings')查询中删除@stones,产品将根据@products模型列出。

product.rb

class Product < ApplicationRecord
  include PgSearch
  pg_search_scope :search_for,
                  against: %i(name body),
                  associated_against: { variations: :name, categories: :name, tags: :name },
                  using: {
                      tsearch: {
                          any_word: true
                      }
                  }

  has_and_belongs_to_many :categories
  has_and_belongs_to_many :tags
  ...
end

tag.rb

class Tag < ApplicationRecord
  has_and_belongs_to_many :products
end

products_controller.rb

  ...
  def index
        if params[:query]
          @products = Product.search_for(params[:query])
          @stones = @products.where.not(products_tags: 'Mouldings')
        else
          ...
        end
  end
  ...

2 个答案:

答案 0 :(得分:1)

尝试include or joins

例如,如果包含标记表,则查询:

      @products = Product.search_for(params[:query]).includes(:tag)
      @stones = @products.where('tag.name != ?', 'Mouldings')

答案 1 :(得分:0)

我找不到我的问题的解决方案(类似)。这是我所做的:

我的模型

class Allergy < ApplicationRecord
   has_and_belongs_to_many :items
end

class Item < ApplicationRecord
   has_and_belongs_to_many :allergies
end

给定过敏清单,我想找到没有那些过敏的物品。示例:

allergies = ['dairy', 'eggs']

所以我创建了两个作用域,它使代码更易于理解(和有用):

class Item < ApplicationRecord
  has_and_belongs_to_many :allergies

  scope :with_allergy, ->(n) { includes(:allergies).where(allergies: {name: n}) }

  scope :free_of, ->(a) { self.all.where.not(id: self.with_allergy(a)) }
end

# I can pass one allergy
Item.free_of('dairy')

# I can pass multiple allergies
Item.free_of(['dairy', 'eggs'])

您可以将“名称”更改为您想要的任何属性(包括 ID)。

我必须创建两个作用域,因为如下:

Item.includes(:allergies).where.not(allergies: {name: n})

未退回与任何过敏无关的商品。相反,它返回至少具有一种关联的记录。

Rails 6.1 的可能解决方案>

Rails 6.1 添加了一个 .missing 方法,该方法返回所有没有任何关联的记录

Item.missing(:allergies) # returns items that do not have any associated allergies.

后者可以与 where 子句结合使用。

来源:https://boringrails.com/tips/activerecord-where-missing-associations