has_many 与 Rails 中范围的关联将不接受参数

has_many association with scope in Rails will not accept arguments

我有 Ad class 条 has_many 条消息。我希望能够 ad.messages(user) 将所有消息发送给该广告上的给定用户。我目前有

has_many :messages, ->(user) { where(to_id: user.id) }

但这不起作用,我不明白为什么。如果没有范围,它会按预期工作并且 returns 所有消息,或者如果我没有参数并硬编码用户 ID,它也可以工作。然而,代码给了我 wrong number of arguments (given 1, expected 0).

has_many关系中proc的参数可以是Message关系中的belongs_to关系,你的情况应该是ad

您可以添加一些自定义过滤条件,即 has_many :messages, ->(ad) { where(ad_name: ad.name) }

那你还是调用ad.messages,不带参数。

因此,如果您想将 user 参数添加到 messages,您可以在 Message 中定义一个 scope

class Message  
  scope :with_user, ->(user) { where(to_id: user.id) }
end

ad.messages.with_user(user)

我相信我已经找到答案了。传递给关联的参数必须是您所在模型的实例,例如,您只能将 ad 传递给 Ad 模型,而不是我尝试做的用户。实现我的目标的正确方法是通过如下扩展。

has_many :messages do
  def user(user)
    where(:to_id => user.id).or(where(:from_id => user.id))
  end
end

黑客攻击 has_many 使其无法正常工作。

您可以只在 class

上定义一个方法
class Ad
  def messages(user_id)
    Message
      .where(ad_id: self.id)
      .where("to_id = :user_id OR from_id = :user_id", user_id: user_id)
  end
end

# somewhere else

Ad.first.messages(some_user_id)

我只想在消息模型上做一个范围。

class Message < ApplicationRecord
...
  scope :by_user, -> (user_id) {where(to_id: user_id)}
...
end

ad = Ad.find(<Id>)
user = User.find(<ID>)
ad.messages.by_user(user.id)

如果你想检查来自和到 ids,你可以像这样修改范围:

scope :by_user, ->(user_id) {
  where("to_id = :user_id OR from_id = :user_id", user_id: user_id)
}