Rails 4 并在 'has_many' SQL 中引用父 ID

Rails 4 and referencing parent id in 'has_many' SQL

TL;DR: 如何在 has_many SQL 子句中使用相应父对象的 ID 来查找子对象?

长版: 我有以下示例代码:

class Person < AR::Base
  has_many :purchases, -> { 
    "SELECT * from purchases
      WHERE purchase.seller_id = #{id}
         OR purchase.buyer_id = #{id}"
  }

这是从 Rails 3 迁移过来的,看起来像

  has_many :purchases, :finder_sql => proc { #same SQL as above# }

我想在一个关联中找到与一个 Person 对象相关联的所有购买,无论这个人是销售对象还是购买对象。

更新: 我更正了SQL,它是反的。对不起!另外:关联只需要是只读的:我永远不会使用这个关联创建记录,所以使用 id 两次应该没问题。但是我 do 希望能够在其上链接其他范围,例如@person.purchases.paid.last_5,所以在一个方法中创建两个关联的总和是行不通的(至少在 Rails 3 中行不通),因为它不是 return 和 AM::Relation但是一个简单的数组。

在 Rails 4.2 中使用上述定义时,我得到

> Person.first.purchases
undefined method `id' for #<Person::ActiveRecord_Relation:0x...>

错误很明显,但是我该如何解决呢?

由于这只是用于表达 has_many 关系的更复杂 SQL 代码的示例(例如,为了性能而使用子选择的多个 JOINS),问题是:

如何在 has_many SQL 子句中使用父对象的 ID?

我认为您的代码根本行不通。您正在定义与两个外键的关联...这意味着如果您想从当前 Purchase 创建一个新的 Person,将使用什么外键,seller_idbuyer_id?那只是没有意义。

无论如何,您得到的错误很清楚:您正在调用一个变量 id,它未在 SQL 代码的块上下文中初始化。

我从您的问题中了解到,解决该问题的更好方法是按以下方式使用关联,然后定义一种方法,为您提供产品所具有的所有人,包括买家和卖家。像这样:

class Purchase < ActiveRecord::Base
  belongs_to :buyer, class_name: 'Person'
  belongs_to :seller, class_name: 'Person'

  def persons
    ids = (buyer_ids + seller_ids).uniq
    Person.where(ids: id)
  end 
end

class Person < ActiveRecord::Base
  has_many :sold_purchases, class_name: 'Purchase', foreign_key: 'buyer_id'
  has_many :buyed_purchases, class_name: 'Purchase', foreign_key: 'seller_id'
end

我的方法是,buyer_idseller_id 是购买的属性,而不是人的属性。

可能是我理解的不正确,请指正。