当有多个关联时,ActiveRecord应该如何编写?
模型是这样的:
class Contract < ActiveRecord::Base
belongs_to :buyer, :class_name => 'Customer', :foreign_key => 'buyer_customer_id'
belongs_to :user, :class_name => 'Customer', :foreign_key => 'user_customer_id'
belongs_to :currency
end
class Customer < ActiveRecord::Base
has_many :as_buyer_in_contracts, :class_name => 'Contract', :foreign_key => 'buyer_customer_id'
has_many :as_user_in_contracts, :class_name => 'Contract',:foreign_key => 'user_customer_id'
end
class Currency < ActiveRecord::Base
has_many :contracts
end
下面是数据:
Contract
+----+-------------------+------------------+-------------+
| id | buyer_customer_id | user_customer_id | currency_id |
+----+-------------------+------------------+-------------+
| 1 | 1 | 3 | 3 |
| 2 | 2 | 2 | 2 |
| 3 | 2 | 1 | 2 |
| | | | |
Customer
+----+-------------------+
| id | name |
+----+-------------------+
| 1 | Terry Brown |
| 2 | Tom Green |
| 3 | Kate White |
| | |
Currency
+----+-------------------+
| id | name |
+----+-------------------+
| 1 | EUR |
| 2 | USD |
| 3 | JPY |
| | |
现在我想找到与名为“Terry”的客户签订的所有合同,如下所示:
Contract.where("customers.name like '%Terry%'").includes(:buyer,:user)
#I want 1 and 3, but it can only get 1
Contract.where("customers.name like '%Terry%'").includes(:user, :buyer)
#If I write "user" before "buyer", then I can only get 3
有人告诉我它可以这样工作:
Contract.join(:customer).where("customers.name like '%terry%'").includes(:user,:buyer)
#It works fine.
我尝试过,它确实有效。但进一步当Contract模型belongs_to其他模型时,比如currency_id,上面的方法就不能再起作用了。
Contract.join(:customer).where("customers.name like '%terry%'").includes(:currency, :user, :buyer)
#>>Mysql2::Error: Unknown column 'customers_contracts.id' in 'field list': ...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
那是因为您不应该将联接与包含结合使用。它还没有得到足够的重视(并且 Rails 中没有警告)但是
您可能会得到结果,但只是偶然。而且很可能它迟早会破裂。
似乎与 include 也存在一些不一致...
如果您需要使用带有 activerecord >= 3.0 的传统外部联接(这里就是这种情况),请使用出色的 squeel gem. 它确实产生了阿雷尔的力量。
尝试一下(安装了 squeel):
开箱即用的连接仅进行内部连接,不包括非相交表,使您的目标在这里不可能实现:买家和买家用户可以是互斥的...
That's because you're not supposed to use joins in conjonction with includes. It hasn't been emphasized enough (and there's no warning in rails) but
You might get results but only by chance. And the odds are it'll break sooner than later.
It seems there's also some inconsistency with includes...
If you need to use a conventional outer join with activerecord >= 3.0 (which is the case here) use the excellent squeel gem. It really yields the power of Arel.
Try out (with squeel installed) :
The out of the box join does inner joining only, which excludes non intersecting table, making your goal impossible here : buyer & user can be mutually exclusive...
您是否尝试过使用连接 :buyer 或 :user 而不是 :customer ?
你的合同模型没有:客户属性/关系
我的猜测是,这相当于
检查你的日志文件以准确查看每种情况下生成的sql - log/development.log
have you tried using joins :buyer or :user instead of :customer?
your Contract model has no :customer attribute/relation
my guess is that will be equivalent to something like
check your log file to see exactly what sql is being generated in each case - log/development.log