合并模型范围的Rails方法

问题描述

| 我不小心注意到我的两个模型有些相似之处。它们的名称是GameItem和OwnedItem。 GameItem只是游戏中的一个项目,而OwnedItem则表示玩家是否拥有该项目,是否在他/她的库存或仓库中等等。我的模型现在就像(为简单起见,我删除了验证和一些无关的代码):
class OwnedItem < ActiveRecord::Base
    belongs_to :user
    belongs_to :game_item
    belongs_to :ownable,:polymorphic => true  # [warehouse|inventory]

  scope :equipped,where(:is_equipped => 1).includes(:game_item)

  scope :item,lambda { |item_type|
    joins(:game_item).
    where(\"game_items.item_type = ?\",item_type ).
    limit(1)
  }

  scope :inventory,where(:ownable_type => \'Inventory\')
  scope :warehouse,where(:ownable_type => \'Warehouse\') 
end



class GameItem < ActiveRecord::Base 

  scope :can_be_sold,where(:is_sold => 1)

  scope :item_type,lambda { |item_type|
    where(\"game_items.item_type = ?\",item_type )
  } 

  scope :item_types,lambda { |item_types|
    where(\"game_items.item_type IN (?)\",item_types )
  }   

  scope :class_type,lambda { |class_type|
    where(\"game_items.class_type = ?\",class_type )
  }

  scope :grade,lambda { |grade|
    where(\"game_items.grade = ?\",grade )
  }
end
请注意game_item.item_type的问题。我在owner_item模型中引用了它,从而破坏了封装并重复了我自己。我实际上如何能够做类似的事情:
user.inventory.owned_items.item_type(\'Weapon\').equipped
就是说,实际上没有在OwnedItem模型中添加重复的代码,而是从GameItem模型中获取了这些信息?     

解决方法

        我认为您在此处定义的关系会给您带来麻烦。您可能会发现最好使用一个简单的用户进行项目加入模型,如下所示:
class User < ActiveRecord::Base
  has_many :owned_items
  has_many :game_items,:through => :owned_items
end

class OwnedItem < ActiveRecord::Base
  belongs_to :user
  belongs_to :game_item

  # Has \'location\' field: \'warehouse\' or \'inventory\'
end

class GameItem < ActiveRecord::Base
  has_many :owned_items
  has_many :users,:through => :owned_items
end
这是一种常见的模式,您有用户以及他们将拥有其实例的某种东西。中间的关系表OwnedItem用于建立GameItem特定实例的任何唯一特征以及它相对于用户的位置。 通常,这种结构避免使用多态关联,如果太随意使用,可能会造成麻烦。尽可能避免多态关联,除非它们处于您关系的最边缘。将它们放在中间会使连接复杂化,并使索引更难调优。 作为原始文档的注释,您可以将其汇总为一个简单的范围,该范围使用用于
where
的哈希方法:
scope :with_item_type,lambda { |types|
  where(\'game_items.item_type\' => types)
}
这将采用数组或字符串参数,并相应地使用
IN
=
。用这种方法实际上非常方便,因为您无需记住要使用哪个。     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...