【问题标题】:Rails 5 custom query using where.not in has and belongs to many association使用 where.not in 的 Rails 5 自定义查询有并且属于许多关联
【发布时间】:2018-03-18 22:31:20
【问题描述】:

我有一个product 模型与has_and_belongs_to_many 关联与tags。我正在尝试创建一个自定义查询以排除具有特定标签的某些产品。使用下面的代码,我得到错误PG::UndefinedColumn: ERROR: column products.product_id does not exist... 如果我从@stones 查询中删除.where.not(products_tags: 'Mouldings'),产品将根据@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
  ...

【问题讨论】:

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


    【解决方案1】:

    试试include or joins。

    例如,如果包含标签表,然后查询:

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

    【讨论】:

    • 我都试过了,但我得到了这个错误PG::UndefinedColumn: ERROR: column products.tag does not exist - 很笨,我想我应该提到产品和标签之间的关联是通过连接表完成的 products_tags
    • 当您调用连接表时,例如 products_tags - 它正在寻找id,除非您指定另一个属性。这里的问题是你传递的是一个字符串,而不是一个 id。 tags 表上的属性名称是什么,它包含值Mouldings。这就是您需要查询的内容。
    • tags 表上的属性是name - 我一直在尝试一切并遇到砖墙......
    • 我更新了答案 - 您需要调用您尝试查询的属性。在这种情况下,tags.name 不仅仅是tags
    • 我快接近了。目前出现错误PG::UndefinedTable: ERROR: missing FROM-clause entry for table "tags" 然后我发现这篇文章stackoverflow.com/questions/25099668/… 所以我将我的代码更新为@stones = Product.includes(:tags).where('tags.name = ?', 'Mouldings').references(:tags),它只显示带有Mouldings 标签的产品,但是当我使用where.not 时出错
    【解决方案2】:

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

    我的模特

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多