【问题标题】:Rails Associations: HABTM?Rails 协会:HABTM?
【发布时间】:2010-11-26 07:52:14
【问题描述】:

大家好,我在考虑这个问题太久后陷入了僵局。

上下文:给定以下模型:

  • 用户
  • 项目
  • 锁定

以下是场景:锁基本上就像“保持”。用户可以在任何给定项目上放置“锁定”以向系统发出不应删除该项目的信号。在锁定被清除之前,项目不会被删除。

这是棘手的部分。锁是它自己的模型,因为我希望多个用户能够锁定任何给定的项目。因此,假设 Bob 锁定了一个项目,该项目尚不存在,因此它为该项目创建了一个锁,以及说明 Bob 当前与该锁相关联的信息。 John 来锁定同一个项目,但已经存在一个锁,所以 John 只是简单地“添加到”同一个锁下。在所有用户选择“解锁”或解除与该锁的关联之前,该锁不会被移除。

我的困惑是我应该如何为这些关系建模。用户当然可以拥有许多锁,每个锁与不同的项目相关联(因为任何给定项目最多可以有一个锁)。锁本身可以有很多用户。从项目的角度来看,每个项目可以有一个锁与多个用户关联。

换句话说,我想像这样访问信息:

item.lock.users # get the users 'locking' the item
user.locks # get the items the user is currently 'locking

也许不需要单独的 Lock 模型,但我认为这是为了表示多个用户可以锁定特定项目。

我认为让事情更复杂的是用户添加的项目,所以我希望有一种方法可以让用户访问项目,例如 user.itemsitem.user

现在我有:

  • 用户拥有并属于许多锁
  • 锁拥有并属于许多用户
  • 用户有很多项目
  • 项目属于用户
  • 项目有一把锁
  • 锁属于物品

这看起来正确吗?

【问题讨论】:

    标签: ruby-on-rails activerecord associations


    【解决方案1】:

    我认为你正在做的事情会奏效,尽管你可能不必使用 habtm。如果一个项目可以有很多锁并且只有在没有锁的情况下才能被删除怎么办。这样您就可以按用户为每个锁添加日期/原因/注释。

    • 用户
      • has_many :locks
      • has_many :items
      • belongs_to :user
      • belongs_to :item
    • 项目
      • belongs_to :user
      • has_many :locks

    尽管item.lock.users 不起作用,这仍然允许您执行user.locks,但通过查看每个锁,您将能够轻松获得用户。

    item.locks.each do |lock|
        puts lock.user
    end
    

    【讨论】:

    • 哇!这么简单,我想得太用力了,我完全没有考虑过。非常感谢人!你已经两次帮助了我:)
    【解决方案2】:

    您不需要锁模型。您可以简单地在用户和项目之间建立一个 habtm 关系:

    class User < ActiveRecord::Base
      has_many :items
      has_and_belongs_to_many :locks, :class_name => "Item"
    end
    
    User.first.items # => [<#Item>, <#Item>, ...] # Items created by user
    User.first.locks # => [<#Item>, <#Item>, ...] # Items locked by user
    
    class Item < ActiveRecord::Base
      belongs_to :user
      has_and_belongs_to_many :lock_users, :class_name => "User"
    end
    
    Item.first.user # => <#User> # Creator of the item
    Item.first.lock_users # => [<#User>, <#User>, ...] # "Lockers" of the item
    

    当然,您必须创建一个连接表,并注意 Rails 期望连接表的名称。您最好为 habtm 指定 :join_table 选项。

    这里的关键是 Rails 中的关系非常灵活。两个表之间可以有多个关系;您可以同时拥有“创建者”和锁定关系,彼此独立。您所要做的就是为关系使用不同的名称。

    【讨论】:

    • 有趣的构造冯康拉德。我很感激,但我认为我更容易理解 rwilliams 的回答。不过谢谢!
    • @vonconrad 我正在为类似的事情苦苦挣扎,我喜欢你的建议。但是,用户锁定项目的代码是什么?我可能有 5 件物品,但我只想锁定其中的 2 件。
    【解决方案3】:

    我可以理解为“考虑太久”。当这个想法潜入我的脑海时,我退后一步,开始处理代码的其他部分。关系似乎会随着时间的推移而显现出来,因为它们真的很方便我们不必编写一堆代码。它们不是必需的,因此,至少在开发阶段,我们可以推迟声明关系,稍后再看看我们需要什么。

    是的,根据实用主义者的说法,我们应该总是提前知道,但在现实生活中,我们经常不得不使用我们的常识和经验来构建一个工作原型,然后对其进行微调。正是在那个微调阶段,我调整了以前并不完全清楚的关系,并调整了我的代码。

    嗅...嗅...天啊,现在我的老板知道我并不完美...嗅...

    回到手头的问题:通常,为了防止意外(或故意)删除的锁定,我在主表中创建一个布尔字段,如果应该清除该记录,请将其设置为 true。对于您正在做的事情,我可能会完全摆脱标志字段并有一个单独的表,该表是要锁定的记录的 ID,以及想要保留记录的用户 ID。如果/当他们认为是时候删除记录时,删除这些用户的记录。当需要进行一些清除时,我会检查该表。类似于:

    delete from table1 where id not in (select distinct(table1_id) from table2)
    

    我不喜欢它的地方是有可能有另一个表充满“保留此记录”记录,那时我添加另一个表以供无法决定需要删除哪些内容的用户终止.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-07
      • 2015-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多