Ruby on rails 将模型范围与轨道方式相结合

Ruby on rails 将模型范围与轨道方式相结合,ruby-on-rails,Ruby On Rails,我无意中发现我的两个模特有些相似。他们的名字是GameItem和OwnedItem。GameItem只是游戏中的一个项目,而OwnedItem则表示玩家是否拥有该项目,该项目是否在其库存或仓库中等等。我的模型现在是这样的(为了简单起见,我删除了验证和一些不相关的代码): 也就是说,没有在我自己的EdItem模型中实际添加重复代码,而是从GameItem模型中获取这些信息?我认为您在这里定义关系的方式会给您带来麻烦。您可能会发现最好使用一个简单的用户到项目联接模型,如下所示: class User

我无意中发现我的两个模特有些相似。他们的名字是GameItem和OwnedItem。GameItem只是游戏中的一个项目,而OwnedItem则表示玩家是否拥有该项目,该项目是否在其库存或仓库中等等。我的模型现在是这样的(为了简单起见,我删除了验证和一些不相关的代码):


也就是说,没有在我自己的EdItem模型中实际添加重复代码,而是从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

这将采用数组或字符串参数,并相应地使用
中的
=
。这样做实际上非常方便,因为您不需要记住要使用哪一个。

嘿,塔德曼,谢谢您的回答:)我实际上有一个用户模型,与您建议的具有相同的关联(我只是没有在这里包括它,但您可以在我自己的EdItem模型中看到要使用的属性)。我还尝试在gameItem中使用has_许多owned_物品,但仍然无法执行诸如user.inventory.owned_物品.game_物品.物品类型(“武器”).装备之类的操作。我在这里还需要多态关联,因为一个项目可以在库存或仓库中。你建议的范围确实非常方便,你的回答肯定值得+1,但我仍然会遇到ownedItem模型的封装问题。我需要创建一个单独的范围,其中包括gameItem模型,以检查类型:/通常,您有两个不同模型的原因是它们所代表的实体完全不同,因此需要它。如果从数据的角度来看,“库存”与“仓库”并没有多大区别,为什么不能将它们组合成一个带有位置指示器属性的单一模型?如果它们有微小的差异,为什么不使用STI?多态关联通常是出了问题的一个标志。你显然不喜欢多态性是rails:)正如我现在看到的,游戏项目有一个可拥有的类型,在这里我可以看到项目是属于库存还是仓库。事实上,在名为Storable的模型中也存在一些类似的功能。到目前为止,这似乎还不错,但我肯定会考虑到你的话。现在改变是很乏味的,但我一直是更好的代码的吸收器。我不介意使用<代码>多态性< /代码>,如果它位于数据结构的边缘,但如果在中间,则会引起麻烦。首先,它使您的
JOIN
语句的复杂性增加了一倍,索引需要复合键,并且您不能使用外键来确保数据完整性。实际上,它们是用来作为最后的手段,或者当替代方案的速度不快时作为一种便利措施。
user.inventory.owned_items.item_type('Weapon').equipped
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
scope :with_item_type, lambda { |types|
  where('game_items.item_type' => types)
}