2010-11-25 121 views
1

嗨,大家好,我在这里思考这个问题太久就陷入僵局。Rails协会:HABTM?

背景:鉴于以下型号:

  • 用户
  • 项目
  • 锁定

这里的场景:一个锁基本上是像一个 '持有'。用户可以在任何给定物品上放置一个“锁定”,以通知系统该物品不应该被删除。在清除锁定之前项目不会被删除。

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

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

因此,换句话说,我想访问的信息少了一些这样的:

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

也许不需要单独锁定模式,但我想这将是为了表示该多个用户可以锁定一个特定的项目。

我觉得更复杂的事情是,用户添加的项目,所以我想有一种方式来访问用户的项目,例如user.itemsitem.user

现在我有:

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

这看起来正确吗?

回答

3

我认为你正在做的事情会工作,虽然你可能不需要使用habtm。如果一个物品可以有多个锁,并且只有在没有锁的情况下才能删除,该怎么办?这样你可以为用户添加每个锁的日期/理由/评论。

  • 用户
    • 的has_many:锁定
    • 的has_many:项目
    • belongs_to的:用户
    • belongs_to的:项目
  • 项目
    • belongs_to的:用户
    • 的has_many:锁

这仍然会允许你这样做user.locks虽然item.lock.users将无法​​正常工作,但通过查看每个锁,你会很容易地能够获得用户。

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

哇!这么简单,我想得太过分了,我完全没有想到它。非常感谢!两次,你已经帮了我:) – 2010-11-25 23:41:33

+0

我很高兴帮助。 – rwilliams 2010-11-25 23:55:05

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中的关系非常灵活。你可以在两个表之间有多个关系;您可以同时拥有“创建者”和锁定关系,彼此独立。你所要做的就是为关系使用不同的名字。

+0

有趣的构建vonconrad。我很感激,但我认为我更容易理解rwilliams的答案。虽然谢谢! – 2010-11-25 23:44:59

1

我可以说“考虑这个太久了”。当这种想法悄悄进入我的脑海时,我退后一步并在代码的其他部分工作。随着时间的推移,关系似乎会显现出来,因为它们让我们能够编写一堆代码非常方便。它们不是必需的,所以至少在开发阶段,我们可以推迟关系的声明,稍后再看看我们需要什么。

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

嗅嗅......嗅......哎呀,现在我的老板知道我并不完美......嗅....

回到手头上的问题:通常情况下,锁以防止意外(或故意)删除,我在我的主表中创建一个布尔字段,如果该记录应该被清除设置为true。对于你在做什么,我可能会完全摆脱标志字段,并有一个单独的表,即要锁定的记录的ID,以及想保留该记录的用户ID。如果他们认为是时候删除记录,请删除这些用户的记录。当是时候做一些清理工作时,我会检查那张桌子。类似的东西来:

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

我不喜欢它的东西是有潜力,有另一个满桌的“保持这个纪录”记载,这就是当我添加另一个表,供用户终止谁可以”决定需要删除的东西。