[英]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.