【问题标题】:Ruby ActiveRecord: How to connect two rooms with an exitRuby ActiveRecord:如何通过出口连接两个房间
【发布时间】:2015-06-02 17:16:22
【问题描述】:

我正在制作一个小型文本冒险游戏,我想使用 ActiveRecord 作为对象关系映射。

我遇到的问题是了解如何使用出口将两个房间连接在一起。 以下事实是给定的:

  • 一个房间可以有多个出口
  • 出口可以有不同的方向(它有一个“方向”字段)。此外,它可能还有其他参数,例如“锁定”等,我想稍后添加。
  • 一个出口连接两个房间。

但是,现在我被卡住了:

我目前拥有的东西

class Room < ActiveRecord::Base
    has_many :exits
    has_many :neighbours, through: :exits
end

class Exit < ActiveRecord::Base

    belongs_to :room, dependent: :destroy
    belongs_to :room_dest, foreign_key: "room_dest_id", class_name: "Room", dependent: :destroy

end

但这是不完整的。例如,room.neighbours 根本不工作。

最让我困惑的是如何让出口以两种方式工作:如果我在一个房间添加出口,它不会出现在另一个房间的room.exits 列表中。

有效的是:(给定一个连接room1room2 的出口) room1.first.exits.first.room_dest(这是room2) 但是room2.exits 是空的,room1.neighbours 显示一个只包含它自己的列表。

这是如何正确完成的?

【问题讨论】:

    标签: ruby activerecord orm rails-activerecord adventure


    【解决方案1】:

    为了让 room.neighbours 工作,我相信你首先需要改变

    belongs_to :room_dest, foreign_key: "room_dest_id", class_name: "Room", dependent: :destroy
    

     belongs_to :neighbour, foreign_key: "room_dest_id", class_name: "Room"
    

    请注意,我删除了dependent: 选项,因为您可能不想在删除出口时破坏房间。你想要依赖: :destroy 与出口的 has_many 关系。

    现在我们已经真正巩固了 Exit 的单向绑定。但仔细想想,“退出”不就是定义上的单向吗?虽然起初这似乎是有限的,但您可以利用它来定义房间的“入口”。那是您从邻居到原始房间的连接。比如:

    has_many :entrances, class_name: "Exit", foreign_key: "room_dest_id"
    

    或者您可以定义一个方法来查询 Exits 并检查 room_id 或 room_dest_id 是否是 Room ID。在这种情况下,我会将“退出”类重命名为更通用的名称。不幸的是,我想不出任何内置的 AR 关联可以为您执行这种多键关联。它不会真正正常工作,因为像 association.build/create 这样的东西不知道要设置哪个键。但它是一个相对简单的方法或一组方法,仍然可以返回一个可以操作的范围:

    has_many :connections, dependent: :destroy # For ease of creating connection, not as useful for querying them
    
    def exits
      Connection.where(["room_id = :id OR dest_room_id = :id", id: self.id])
    end
    
    def neighbours
      exits.map do |conn|
        conn.room_id == self.id ? conn.dest : conn.source
      end
    end
    

    如果您确实希望某些连接是单向的,则可以使查询更加复杂。或者编写基于此的其他方法,因为它不会立即执行。您仍然可以在其上链接 .first()、另一个 .where() 等。

    【讨论】:

    • 非常感谢!将它们设为定向是一个非常好的主意;让控制器弄清楚我们向哪个方向移动,模型不必关心。另外,感谢dependent: :destroy 提示。你每天都会学到新东西:-)
    猜你喜欢
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多