繁体   English   中英

Rails 'includes' 和 'where' 与 belongs_to 和 has_many 关联

[英]Rails 'includes' and 'where' with belongs_to and has_many association

我有模型:

class Order < ApplicationRecord
  acts_as_paranoid
  has_paper_trail

  enum status: %i[created in_process]

  has_many :order_containers
  has_many :line_items
end

class LineItem < ApplicationRecord
  acts_as_paranoid
  has_paper_trail

  enum status: %i[in_process collected]

  belongs_to :order
  belongs_to :variant
end

class Variant < ApplicationRecord
  acts_as_paranoid
  has_paper_trail

  has_many :line_items

  belongs_to :product

  validates :barcode, presence: true
end

class Product < ApplicationRecord
  acts_as_paranoid
  has_paper_trail

  belongs_to :isles, required: false
  has_many :variants

  validates :name, :volume, :sku, :price, presence: true
end

class Isle < ApplicationRecord
  acts_as_paranoid
  has_paper_trail

  has_many :products
  validates :name, presence: true
end

我只需要输出产品属于特定岛屿的那些订单。 例如,如果订单中没有属于我需要的岛屿的产品,则不需要显示该订单及其产品。 如果订单中有属于特定岛屿的产品,例如(isle.id 1),则需要撤回此类订单以及属于该部门的产品

我试试这个:

@products = Order.includes([:line_items, :variants, :products, :isles]).where('products.isle_id = isle.id').references(:orders)

但我得到了错误:

ailure/Error: return { "#{root_name}": [] } if records.blank?
 
 ActiveRecord::StatementInvalid:
   PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "products"
   LINE 1: ..."orders" WHERE "orders"."deleted_at" IS NULL AND (products.i...

如果我设计得不好我很抱歉,我是一个新手开发人员,这是我的第一个任务)

这将从 Isle#1 返回 Order#1 中的所有产品。 如果订单有来自同一产品的多个变体,它将返回重复的产品,如果这不是您需要的,请将.distinct添加到这些查询中。

>> order = Order.first
>> isle  = Isle.first

>> Product.joins(variants: { line_items: :order }).where(isle_id: isle, line_items: { order_id: order })
=> [#<Product:0x00007f1551fc4820 id: 1, isle_id: 1>,
    #<Product:0x00007f1551fc4258 id: 2, isle_id: 1>]

您可以向Order添加一些关联来简化此操作:

class Order < ApplicationRecord
  has_many :line_items

  has_many :variants, through: :line_items
  has_many :products, through: :variants
end
>> Order.first.products.where(isle_id: Isle.first)
=> [#<Product:0x00007f154babcb30 id: 1, isle_id: 1>, 
    #<Product:0x00007f154babca18 id: 2, isle_id: 1>]

更新

确保您正确地创建了关联。 使用create! save! 控制台中的方法来引发任何验证错误。

# NOTE: create a new order with two products in two different isles
#       just add the required attributes from your models.

order = Order.create!(line_items: [
  LineItem.new(variant: Variant.new(product: Product.new(isle: (isle = Isle.create!)))),
  LineItem.new(variant: Variant.new(product: Product.new(isle: Isle.new)))
])

# NOTE: verify that you have two products

>> order.products
=> [#<Product:0x00007f6f1cb964e0 id: 1, isle_id: 1>,
    #<Product:0x00007f6f1cb963f0 id: 2, isle_id: 2>]

# NOTE: filter by isle

>> order.products.where(isle_id: isle)
=> [#<Product:0x00007f6f1ccda630 id: 1, isle_id: 1>]

>> order.products.where(isle_id: 2)
=> [#<Product:0x00007f6f1d140cd8 id: 2, isle_id: 2>]

https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many

https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

你对它的结构有很多问题。 如果您真的只想要特定岛屿的产品,那么您应该能够使用:

@products = Product.where(isle_id: my_isle_variable)

您可能还需要更新模型,以便 Product belongs_to :isle (单数而不是复数)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM