【问题标题】:How can I delegate to scope ? rails如何委派给范围?导轨
【发布时间】:2016-07-12 17:58:21
【问题描述】:

我有:

class UserItem < ActiveRecord::Base

  belongs_to :user
  belongs_to :item

  scope :equipped, -> { where(equipped: true) }
end

class Item < ActiveRecord::Base
   has_many :user_items
   has_many :users, through: :user_items

   scope :armor, -> { where(type: 'Armor') }
   delegate :equipped, to: :user_items

end

编辑:

如果我尝试

User.first.items.equipped => undefined method 'equipped' for #&lt;ActiveRecord::Associations::CollectionProxy []&gt;

User.first.items.armor.equipped => undefined method 'equipped' for #&lt;ActiveRecord::AssociationRelation []&gt;

如何委派给作用域?

【问题讨论】:

  • 嗨 Matrix,我已经更新了我的答案,解释了为什么你实际上可能不想做你想做的事情,以及你需要什么方法来使用父范围检索子项目。
  • 我一定是误解了这个问题,因为我从你的问题中确定merge 是解决方案。祝你好运!

标签: ruby-on-rails ruby-on-rails-4 scope delegates


【解决方案1】:

您不能轻易委托给作用域,您也不想这样做,因为它会从目标类 (UserItem),而不是子类返回对象。

相反,您可以非常简单地合并范围:

class UserItem < ActiveRecord::Base
  scope :equipped, -> { where(equipped: true) }
end

class Item < ActiveRecord::Base
  scope :equipped, -> {joins(:user_items).merge(UserItem.equipped)} 
end

=> Item.equipped
=> collection of items for which they have a user_item association that is equipped

编辑:有关此功能的一些文档。

Using Named Scopes Across Models with ActiveRecord#Merge http://apidock.com/rails/ActiveRecord/SpawnMethods/merge

再次编辑:

如果您真的想从您在 Item 上调用的方法返回 UserItems 的集合,那么您可以执行以下操作:

class Item
  class << self
    delegate :equipped, to: :UserItem
  end 
  ...

但这将返回集合中的 UserItems,而不是 Items。这就引出了一个问题,为什么要委托这个? 如果你想要一个项目的集合,并且你想通过一组配备的用户项目来限制这些项目,那么使用merge

【讨论】:

  • 如果我想在 Item 中使用范围,我会使用:scope :equipped, -&gt; {where( inventory_items: { equipped: true }) } 但这不是我的问题 ^^(我不反对)
  • @Matrix 我的例子中的作用域在Item模型中,它加入了用户项目模型并使用equipped作用域来限制返回的items被配备的user_items .除非我严重误解了您的问题,否则这就是您想要的吗?本质上这是select items.* from items joins user_items where user_items.equipped = true。是否要返回 UserItem 对象的集合?
  • 不,您已经理解问题,但在项目模型中我可以添加:scope :equipped, -&gt; {where( user_items: { equipped: true }) }(将“库存”替换为“用户”,这是我上次 com 中的一个错误)并且它工作正常。但我的问题是:如何在 UserItem 中使用范围而不重新定义 Item 类中的范围?
  • 您可以使用merge 来使用关联模型的范围,而无需在子类中重新定义它们。您不能将委托用于范围。
  • @Matrix 好吧,我确定这不是您想要的,或者是一个坏主意,但我添加了一个示例,该示例将equipped 方法直接传递给 UserItem 类。 . 以及我认为这是错误的原因。
猜你喜欢
  • 2019-08-15
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
  • 2018-04-11
  • 2020-12-24
  • 2023-03-07
  • 2013-12-06
相关资源
最近更新 更多