我如何委托范围?轨道

时间:2016-03-25 00:12:15

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

我有:

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 =&gt; undefined method 'equipped' for #<ActiveRecord::Associations::CollectionProxy []>

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

我如何委托范围?

1 个答案:

答案 0 :(得分:4)

您不能轻易地委托范围,也不想,因为它会从目标类(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上调用的方法返回一个UserItem集合,那么你可以这样做:

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

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