Ruby on rails RoR ActiveRecord查询产生意外结果
我有一个测试应用程序,模型如下Ruby on rails RoR ActiveRecord查询产生意外结果,ruby-on-rails,active-record-query,Ruby On Rails,Active Record Query,我有一个测试应用程序,模型如下 ActiveRecord::Schema.define(version: 20140102023300) do create_table "customers", force: true do |t| t.string "name" t.datetime "created_at" t.datetime "updated_at" end create_table "order_products", force: true
ActiveRecord::Schema.define(version: 20140102023300) do
create_table "customers", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "order_products", force: true do |t|
t.integer "customer_id"
t.integer "order_id"
t.integer "product_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "orders", force: true do |t|
t.text "description"
t.integer "customer_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "products", force: true do |t|
t.string "description"
t.float "item_price"
t.datetime "created_at"
t.datetime "updated_at"
end
end
class Customer < ActiveRecord::Base
has_many :orders
end
class Order < ActiveRecord::Base
belongs_to :customer
has_many :order_products
end
class OrderProduct < ActiveRecord::Base
belongs_to :order
end
这些协会如下:
ActiveRecord::Schema.define(version: 20140102023300) do
create_table "customers", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "order_products", force: true do |t|
t.integer "customer_id"
t.integer "order_id"
t.integer "product_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "orders", force: true do |t|
t.text "description"
t.integer "customer_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "products", force: true do |t|
t.string "description"
t.float "item_price"
t.datetime "created_at"
t.datetime "updated_at"
end
end
class Customer < ActiveRecord::Base
has_many :orders
end
class Order < ActiveRecord::Base
belongs_to :customer
has_many :order_products
end
class OrderProduct < ActiveRecord::Base
belongs_to :order
end
然后在Rails控制台中,我加载了一个包含客户列表的变量:
@customers = Customer.all
当我运行此命令时:@customers.find(1).orders
我正确获取
Order id: 1, description: "description for order 1", customer_id: 1, created_at: "2014-01-02 02:51:36", updated_at: "2014-01-02 02:51:36">,
Order id: 4, description: "description for order 4", customer_id: 1, created_at: "2014-01-02 02:51:36", updated_at: "2014-01-02 02:51:36">]
然后我想查询每个订单中的项目。为了简单起见,让我们假设我想在订单1中为客户1找到产品
我尝试了以下查询:@customers.find(1).orders.find(1).order\u products
,但我得到了以下结果:
OrderProduct id: 1, customer_id: 1, order_id: 1, product_id: 1, created_at: "2014-01-02 02:51:36", updated_at: "2014-01-02 02:51:36">,
OrderProduct id: 2, customer_id: 1, order_id: 1, product_id: 2, created_at: "2014-01-02 02:51:36", updated_at: "2014-01-02 02:51:36">,
OrderProduct id: 6, customer_id: 2, order_id: 1, product_id: 5, created_at: "2014-01-02 02:51:36", updated_at: "2014-01-02 02:51:36">,
OrderProduct id: 7, customer_id: 2, order_id: 1, product_id: 6, created_at: "2014-01-02 02:51:36", updated_at: "2014-01-02 02:51:36">
它似乎正在返回查询的orders.find(1).order\u products
部分的结果,因为所有结果都是order\u id:1
。问题是,此结果集包括客户id:1
和2
的结果
我真正想看到的是
订单1
中的产品,用于客户1
。您能帮我理解我需要的正确查询吗?您的查询基本上返回属于订单的所有OrderProduct
——您构建查询的方式,对于用户来说基本上是不可知的。例如,根据您的模式,客户#1拥有订单#1,但订单#1也属于客户#2。因为查询是针对属于订单的订单产品,订单#1将同时返回customer#1和customer#2的条目
由于OrderProduct
具有指向Customer
和Order
的外键,因此您可以尝试更明确的查询来检索属于特定客户和订单的订单产品:
OrderProduct.where(:customer_id => 1, :order_id => 1)
更新:
您的seeds.rb中存在一些问题,这些问题会导致复杂的关系。您已经定义了订单
属于客户
,但您的数据库种子表明订单属于多个客户
orderproducts = OrderProduct.create([
{:customer_id => 1, :order_id => 1, :product_id => 1},
{:customer_id => 1, :order_id => 1, :product_id => 2},
{:customer_id => 1, :order_id => 2, :product_id => 4},
{:customer_id => 1, :order_id => 2, :product_id => 7},
{:customer_id => 1, :order_id => 2, :product_id => 3},
{:customer_id => 2, :order_id => 1, :product_id => 5}, # Order 1 already belongs to Customer 1
{:customer_id => 2, :order_id => 1, :product_id => 6}, # Order 1 already belongs to Customer 1
{:customer_id => 2, :order_id => 2, :product_id => 3}, # Order 2 already belongs to Customer 1
{:customer_id => 2, :order_id => 2, :product_id => 4}, # Order 2 already belongs to Customer 1
])
确保每个订单与单个客户关联后,可以发出原始查询以检索属于用户订单的订单产品:
@customers.find(1).orders.find(1).order_products
#=> OrderProduct id: 1, customer_id: 1, order_id: 1, product_id: 1, created_at: "2014-01-02 02:51:36", updated_at: "2014-01-02 02:51:36">,
#=> OrderProduct id: 2, customer_id: 1, order_id: 1, product_id: 2, created_at: "2014-01-02 02:51:36", updated_at: "2014-01-02 02:51:36">,
如果您知道customer\u id
和order\u id
,您可以这样查询OrderProduct
OrderProduct.where(customer_id: 1, order_id: 1)
但是,您也可以利用活动记录关联来实现以下功能
Customer.find(1).orders.first.order_products # to get all order_products of the first order of the customer.
或
请参阅中的这本优秀指南,您订购的产品似乎是订单和产品的联接表。您可能想看看这里描述的有很多:通过关联:哇。。。你答案的第一部分看起来很熟悉。但第二部分只是从OP的问题中重新整理代码——这是行不通的。客户和订单之间的关系是多对多的,因此您建议的查询(即,从问题中重新筛选)可能会返回属于多个用户的订单产品。我感谢您对此问题的回答。我发现它很有用。作为对zeantsoi评论的回应,我已经测试了这个答案的第二部分,它对我不起作用。@zeantsoi-:)。。我在贴完我的帖子后看到了你的帖子。但你确实比我抢先一步。对于客户订单,您如何看待多个<代码>订单
与单个客户关联,是否?至少模式似乎表明了这一点。模型定义了一个属于/有很多关系,但是seeds.rb
表明了一个多对多关系。这主要是数据问题,而不是代码问题。看起来您的种子数据有一些问题。我发布了一个解决方案,建议1)按原样修复,2)纠正种子数据的方法,以使您的原始查询正常工作。精彩的zeantsoi!!我总是非常感谢专家们的指导。非常感谢。:-)Zeantsoi,我能再问一个问题吗?您会从OrderProcuct模型的模式中删除customer_id吗?(以及相应的种子数据)其他Ruby Noobie(如我)的注意事项:@customers.find(1).orders.find(1).order\u products确实返回该订单的产品,但@customers.find(1).orders.find(2).order\u products失败,因为该客户的下一个order\u id是4。所以@customers.find(1).orders.find(4).order\u产品有效。如果要枚举/迭代客户订单,请使用@customers.find(1).orders[0]访问数组(ActiveRecord::Associations::CollectionProxy:object),因为您的customer
模型当前与OrderProduct
(因此这种关系实际上是不存在的,除非通过中间的订单模型)。您可能应该研究一下——这是一个针对这种特殊关系的完美用例。