Rails协会:HABTM?

时间:2010-11-25 22:58:30

标签: ruby-on-rails activerecord associations

嘿伙计们,在考虑了这个问题太长时间之后,我处于僵局。

背景:给出以下模型:

  • 用户
  • 项目
  • 锁定

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

这是棘手的部分。锁是它自己的模型,因为我希望多个用户能够锁定任何给定的项。因此,假设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

现在我有:

  • 用户拥有并属于许多锁
  • lock拥有并且属于许多用户
  • 用户有很多项目
  • 项目属于用户
  • 项目有一个锁
  • lock属于item

这看起来是否正确?

3 个答案:

答案 0 :(得分:3)

我认为你所做的事情虽然你可能不必使用habtm。如果一个项目可以拥有多个锁定并且只能在没有锁定时删除,该怎么办?这样,您可以为用户添加每个锁的日期/原因/注释。

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

虽然user.locks无效,但您仍然可以item.lock.users这样做,但通过查看每个锁定,您可以轻松获得用户。

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

答案 1 :(得分: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中的关系非常灵活。您可以在两个表之间建立多个关系;你可以同时拥有'创建者'和锁定关系。您所要做的就是为关系使用不同的名称。

答案 2 :(得分:1)

我可以说“长时间思考这个问题”。当那个想法进入我的脑海时,我会退后一步,继续处理代码的其他部分。随着时间的推移,关系似乎会显露出来,因为它们真的很方便我们编写一堆代码。它们不是必需的,所以,至少在开发阶段,我们可以推迟关系的声明,稍后看看我们需要什么。

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

嗤之以鼻......嗤之以鼻......杰兹,现在我的老板知道我不完美......嗤之以鼻......

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

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

我不喜欢的事情就是有可能让另一个表充满“保留此记录”记录,那就是我为用户添加另一个表以终止谁无法决定需要删除哪些内容