当前位置: 首页 > 面试题库 >

在Rails 3中为单个记录使用多个外键?

穆毅然
2023-03-14
问题内容

我正在开发一个应用程序,该程序将管理注册课程的学生。该应用程序将具有可以登录并操纵学生的用户。用户还可以对学生进行评论。因此,我们的三个主要班级是学生,用户和评论。问题是我需要将个人评论与其他两个模型相关联:用户和学生。所以我从这样的一些基本代码开始…

class Student < ActiveRecord::Base
  has_many :comments
end

class User < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :student
  belongs_to :user
  attr_accessible :comment
end

因此,在注释表中,单个记录将具有以下字段:

id
comment
student_id
user_id
created_at
updated_at

这带来了几个问题。首先,用于创建关联对象的漂亮的Rails语法会分解。如果要发表新评论,则必须在外键之间进行选择。所以…

User.comments.create(attributes={})

或者

Student.comments.create(attributes={})

另一种选择是任意选择一个外键,然后将其手动添加到attrs哈希中。所以…

User.comments.create(:comment => "Lorem ipsum", :student_id => 1)

这个选项的问题是我必须在我的Comment模型中的attr_accessible下列出student_id。但是我的理解是,这会带来安全隐患,因为有人可以从技术上来利用大量分配将评论与其他学生重新关联。

这就引出了另一个有关通常使用Rails进行数据建模的问题。我目前在Rails中构建的应用程序是几年前我最初在PHP /
MySQL中编写的应用程序。当我第一次学习SQL时,非常重视规范化的思想。因此,例如,如果您有一个存储姓名和地址的联系人表,则将使用许多外键关系来避免重复数据。如果您有状态列,则不想直接列出状态。否则,您可能有成千上万的行,其中全部包含“
Texas”之类的字符串值。最好有一个单独的状态表,并使用外键关系将其与您的联系人表关联。我对良好的SQL理论的理解是,任何可能重复的值都应分为各自的表。当然,为了完全规范化数据库,您可能最终在contacts表中有很多外键。(state_id,gender_id等)

那么,如何以“ Rails方式”实现这一目标呢?

为了澄清(很抱歉,我知道这已经很长时间了),我考虑了另外两种常见方法:“ has_many:through
=>”和多态关联。据我所知,这两种方法都不能解决上述问题。原因如下:

在类似博客的情况下,“ has_many:through=>”效果很好。因此,我们有“注释”,“文章”和“用户”模型。用户在文章中有很多评论。(顺便说一下,这样的例子出现在Apress的BeginningRails3中。不错的书。)问题在于,要使之有效(如果我没记错的话),每篇文章都必须属于特定的用户。在我的情况下(此处的Student模型类似于Article),没有一个用户拥有一个学生。因此,我不能说用户在学生中有很多评论。可能有多个用户评论同一个学生。

最后,我们有多态关联。假设没有一条记录需要属于一个以上的外来类,这对于多个外键非常有用。在RailsCasts第154集中,Ryan
Bates给出了一个示例,其中注释可能属于文章或照片或事件。但是,如果单个评论需要属于多个评论,该怎么办?

因此,总而言之,我可以通过手动分配一个或两个外键来使User,Student,Comment场景正常工作,但这不能解决attr_accessible的问题。

在此先感谢您的任何建议!


问题答案:

当我开始使用Rails时,我遇到了您的确切问题。如何在确保对association_ids进行保护的同时,在create方法中整齐地设置两个关联。

Wukerplank是正确的-您无法通过批量分配设置第二个关联,但仍可以直接在新行中分配association_id。

这种关联分配非常常见,并且在我的代码中乱七八糟,因为在许多情况下,一个对象具有多个关联。

另外,要明确一点:多态关联和has_many:through根本无法解决您的情况。您有两个独立的关联(评论的“所有者”和评论的“主题”)-无法将它们合理化为一个。

编辑:这是您应该如何做:

@student = Student.find_by_id(params[:id])
@comment = @student.comments.build(params[:comment]) #First association is set here
@comment.user = current_user #Second association is set here
if @comment.save
  # ...
else
  # ...
end

通过使用Object.associations.build,Rails会自动创建一个新的“关联”对象,并在保存时将其与Object关联。



 类似资料:
  • 我有一个小的python项目,它有如下结构-- 我计划使用默认日志模块将消息打印到stdout和一个日志文件。要使用日志模块,需要进行一些初始化- 目前,我在开始记录消息之前在每个模块中执行此初始化。是否有可能在一个地方只执行一次初始化,以便通过在整个项目中进行日志记录来重用相同的设置?

  • 我发现这个问题与不同的编程语言或不同的数据库有关 我正在尝试创建一个门户来生成多项选择查询,前端将发送给我一个巨大的json在某些时候会有一个问题对象数组每个对象应该有: 问题 正确答案 错误答案列表 ( 最少 2 最多 4 ) 课程特定对象的 ID... 我需要(如果可能的话)在postgresql数据库的单个记录中存储错误答案(字符串)列表 这是我的课 这正是我有一些疑问的地方(让我们暂时跳过

  • 给定:我在Kafka中有两个主题,假设主题A和主题B。Kafka流从主题A中读取一条记录,对其进行处理,并产生与所消耗记录相对应的多条记录(假设recordA和recordB)。现在的问题是我如何使用Kafka流来实现这一点。 在这里,读取的记录是消息;处理之后,它返回一个消息列表。如何将此列表划分为两个生产者流?任何帮助都将不胜感激。

  • 我试图保存多个记录通过 但是从上面来看,只创建了第一个数组。我哪里做错了?感谢您的帮助。

  • 我基本上一直在尝试通过使用JFrame并切换出2个JPanel(一个用于菜单,一个用于实际游戏)来为游戏制作菜单。我正在尝试实现我能想到的最基本的格式,但似乎无法让它工作。如果有人能解释代码的错误,我将不胜感激。 这是我的JFrame、菜单面板和ActionListener actionPerformed调用在此类中创建的面板 同样,如果有人能向我解释一下这段代码的错误,我将不胜感激。谢谢

  • 问题内容: 我正在为客户/订单系统定义一个数据库,其中有两种高度不同的客户类型。因为它们是如此不同,所以只有一个客户表会非常丑陋(因为空列对于一种类型是毫无意义的,所以充满了空列)。 他们的订单虽然格式相同。我的订单表中是否可以有一列同时具有两种客户类型的外键?我已经在SQL Server中进行了设置, 创建 关系没有问题,但是我还没有尝试插入任何数据。 另外,我正在计划将nHibernate用作