【问题标题】:Joining a pivot table to another table (HABTM join HABTM and model associations)将数据透视表连接到另一个表(HABTM 连接 HABTM 和模型关联)
【发布时间】:2011-07-09 22:38:46
【问题描述】:

假设我正在构建一个拥有许多博客和许多用户的引擎。用户可以有很多博客,博客也可以有很多用户(用户 hasAndBelongsToMany 博客)。我将创建一个名为 users_blogs 的数据透视表,如下所示:

id user_id blog_id role

1  1       1       admin
2  1       2       poster
3  2       2       admin

所以,用户 1 属于博客 1 和 2,用户 2 属于博客 2。用户 1 是博客 1 中的管理员,博客 2 中的海报,用户 2 是博客 2 中的管理员。

也会有帖子。 users_blogs 会有很多帖子,帖子可以有很多 users_blogs。它们将与如下所示的数据透视表连接:

id users_blog_id post_id
1  2             1
2  3             1

因此,参考 users_blogs,博客 2 上的用户 1 与博客 2 上的用户 2 协作创建了帖子 1。

我对 MVC 比较陌生,所以我想知道 A) 第一个表中的“角色”数据是否在它应该在的位置?B) 是否有更正确的方法来执行此结构?框架会为我创造奇迹,我只是想确保这是有意义的,并且我有正确的命名约定。我正在使用 Cakephp,但我也认为这个问题可以由 Rails 程序员来回答。

谢谢!

【问题讨论】:

    标签: mysql ruby-on-rails model-view-controller cakephp model


    【解决方案1】:

    看来您走在正确的轨道上。如果我理解你的话,应该是这样的:

    我没有完全理解你的一个陈述,所以我假设post belongsTo 一个blog 最喜欢。

    第一个问题是,您的“数据透视表”命名约定必须按字母顺序排列 - 所以它应该是 blogs_users,而不是 users_blogs。看起来很小,但否则不会起作用。

    协会:

    blog hasMany post
    post belongsTo blog
    
    user hasAndBelongsToMany blog //allowing more than one user to be associated to a blog
    blog hasAndBelongsToMany user
    
    user hasAndBelongsToMany post //allowing more than one user to be associated to a post
    post hasAndBelongsToMany user
    
    role hasAndBelongsToMany user //better to keep roles in a table that just a string
    user hasAndBelongsToMany role //use 'with'=>'blogs_users' in your association
                                  between user/roll
    

    表格:

    users            (id, name, ...etc)
    blogs            (id, title, ...etc)
    roles            (id, role)
    blogs_users      (id, user_id, role_id, blog_id)
    posts            (id, title, blog_id)
    posts_users      (id, post_id, user_id)
    

    更新:

    我在这方面不是最好的——我自己还在学习,但是——在我脑海中,你可以通过这样的方式从用户 1 创建的博客 1 中获取帖子:

    $blogId = '1';
    $userId = '1';
    $posts = $this->Post->find('all', array(
        'conditions' => array(
            'User.id' => $userId,
            'Blog.id' => $blogId
        )
    );
    

    【讨论】:

    • 您对字母顺序的看法是正确的,您回答了我的第一个问题,即“角色”应该驻留在数据透视表中。假设用户 1 有 100 个博客。如果我们想从博客 #1 中获取用户 1 的帖子,我们必须获取所有的 posts_users,然后获取所有的帖子,然后匹配 blog_id 和 user_id。相反,如果我们有一个 blogs_users_posts 表会怎样。我们将从代表用户 1 和博客 #1 的 blogs_users (blog_user_id) 中获取一条记录,并在 blogs_users_posts 中找到具有该 blog_user_id 的所有帖子。这样做似乎比上述方式更快。这是正确的吗?谢谢!
    • 如果您想从博客 #1 获取用户 1 的帖子,我们假设您已经拥有博客 ID 和 user_id - 所以 - 只需从该特定博客中提取任何帖子(帖子表有 blog_id) ,然后设置您只想要 user_id = 1 的帖子的条件。也许我错过了什么?
    • 我想我意识到我的问题出在哪里。我认为将 blog_id 添加到 users_posts 表中会有一些价值。如果我将 user_id 和 blog_id 放在一个表中,我可以在该博客中找到该用户的所有 post_id,而无需离开该表。这真的只对计算博客中的用户帖子有用,也许还有其他用途?如果我在一个表中同时拥有 user_id 和 blog_id,为什么不将它们合并为 users_blog_id 并引用 users_blogs。这将使表格与 users_posts 大小相同,并提供更多信息。我认为它也可以节省查询时间,但事实并非如此。
    • 很高兴您成功了! :) 我理解你的逻辑——这是有道理的——我想它可以以任何一种方式工作,但我一直非常喜欢将数据(比如哪个用户拥有哪个博客)保存在一个地方。很高兴听到它这样做不是表演! :)
    • 最后一个问题:你会运行什么 post->find 表达式来获取博客 1 和用户 1 的所有帖子?
    【解决方案2】:

    这不是一个真正的 rails、cakephp 或 mvc 问题,但您的关系数据库架构看起来应该基于您所描述的内容。

    【讨论】:

    • Cake 和 Ruby 在命名约定正确时会做很多“自动”的事情。我也在问这种建立这些关联的方式是否是最佳实践,或者有更好的方法来做到这一点。
    【解决方案3】:

    我不知道 Cakephp,但是关于你加入 table 的三个问题会破坏 Rails 中的 habtm 关系。

    1) 连接表默认命名为blogs_users。 2)连接表不能有任何其他属性,例如role。 3) 连接表不能有id

    所以你的blogs_users 表应该只有blog_iduser_id,否则你会得到错误。

    如果您希望您的连接表成为 Rails 中的完整模型,您将需要使用has_many :through 关系。所以

    class User
      has_many :user_blogs
      has_many :blogs, :through => :user_blogs
    end
    
    class UserBlog
      belongs_to :blog
      belongs_to :user
    
      validates_presence_of :role, :in => ALLOWED_ROLE_NAMES # Example of logic in this model
    end
    
    class Blog
      has_many :user_blogs
      has_many :users, :through => :user_blogs
    end
    

    【讨论】:

    • 他说他用的是CakePHP,所以#2) 不正确,#3) 也不正确
    • 我听说 Cakephp 与 Rails 非常相似。如果 Rails 确实不允许您这样做,而 CakePHP 确实允许,那么这个问题不适合 Rails 答案。对此感到抱歉。
    猜你喜欢
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多