【问题标题】:Associating two tables that both belong to a third, independent table关联两个都属于第三个独立表的表
【发布时间】:2014-07-27 02:46:15
【问题描述】:

我有三张桌子:

Topics        Jobs          Requests
-----         ----          --------
title         description   request
description   worker_id     user_id   
              topic_id      worker_id
                            topic_id

工人为每个主题创建一个工作。然后,用户可以请求工作人员完成这项工作。

我目前的联想:

class Topic < AR::Base
  has_many :jobs
  has_many :worker, through: :jobs
end

class Job < AR::Base
  belongs_to :topic
  belongs_to :worker
  has_many :requests
end

class Request < AR::Base
  belongs_to :user
  belongs_to :worker
  belongs_to :topic
  has_one: :job, through: :topic   #This doesn't work, lol.
end

问题:

我不确定请求应该属于主题还是作业。

我需要:

  • 访问请求的主题信息比访问作业信息更频繁,但仍然有可用的作业信息。

  • 根据主题和工作人员创建请求,而不是作业。 (这很重要。)

  • 列出给定主题的所有请求。

  • 为请求预加载主题和作业信息。 (也很重要。)

我对直接关联请求和作业犹豫不决,因为作业包含一些不应该对所有请求都可用的信息。通过该关联,任何请求都可以访问该信息,但这可能不是什么大问题。

另外,因为我需要请求和主题之间如此紧密的关联,所以使用这种关联似乎更合乎逻辑,但是我失去了轻松的工作访问权限。 (对于上述关联,我必须使用自定义方法:Job.find_by(topic_id: self.topic_id, worker_id: self.worker_id),它不允许预加载或多个请求。)

去这里最好的方式是什么?

(如果有更好的标题,请告诉我。)

【问题讨论】:

    标签: ruby-on-rails postgresql activerecord database-design ruby-on-rails-4


    【解决方案1】:

    因为Topic总是属于Job,所以Request应该属于Job并且只属于Job。您始终可以遍历与 Topic 的关联。这在逻辑上是有道理的,因为用户要求工人做一份工作。该主题只是有关该工作的附加信息。如果用户请求一个主题,你怎么知道他们想要完成什么工作?

    另外说明,由于工作人员与作业相关联(任何工作人员都不会执行不是他们创建的工作),因此 worker_id 应该只在作业模型上,而不是在请求模型上。

    把你的桌子换成这个,你应该很好:

    Topics        Jobs          Requests
    -----         ----          --------
    title         description   request
    description   worker_id     user_id   
                  topic_id      job_id
    

    【讨论】:

    • 是的,这是真的。用户请求工作而不是主题,所以我想这就是我的答案。从技术上讲,我仍然可以通过 topic_id 和 worker_id 找到工作——它只是不合适的关联。如果我从请求中删除 worker_id,我怎样才能找到一个工人的所有请求?通过工作?感谢您的帮助。
    • 通过topic_id找工作确实是这样,我错过了。要获得对工作人员的所有请求会比较棘手,但最好使用 has_many :through 关联。工人通过作业有许多请求。例如,这样您就可以引用 Worker.first.requests.load 来获取第一个工作人员的所有请求。
    • 这是有道理的。如果我要根据主题/工作人员 ID 的请求找到工作,那么该关联将如何工作,如果有的话?只是想确保我理解这两个选项。欣赏它。
    • 不确定我是否理解。如果您有请求,您可以通过 job_id 找到工作。如果你只有一个 worker_id 和一个 topic_id,你可以运行 Ruby 方法 select for Job.all.select{ |job| job.worker_id == some_worker_id && job.topic_id == some_topic_id }。这将为您提供所有带有您正在检查的工作人员和主题 ID 的工作。这能解决您的问题吗?
    • 如果我的回答对你有用,你会愿意投票并选择它吗?这就是我们老鼠的一点奶酪。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2021-05-17
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多