Rails在一个表上连接多个模型

时间:2015-04-20 17:33:01

标签: ruby-on-rails ruby

rails的新手(使用4.1),将小型项目管理工具作为学习项目。我遇到了一个稍微复杂的模型关联,我想确保我在这里正确的轨道,并询问如何扩展它。

考虑这种情况:

型号:

class Website < ActiveRecord::Base

    has_many :website_user
    has_many :users, through: :website_user
    has_many :tasks, through: :website_user

end

class User < ActiveRecord::Base

    has_many :websites, through: :website_user
    has_many :website_user

end


class WebsiteUser < ActiveRecord::Base

   belongs_to :website
   belongs_to :user
   belongs_to :role
   has_many :tasks

end

class Task < ActiveRecord::Base

    belongs_to :website_user
    has_one :website, through: :website_user

end

class Role < ActiveRecord::Base
    has_many :website_user
end

DB:

create_table "roles", force: true do |t|
    t.string "name"
end

create_table "tasks", force: true do |t|
    t.text    "description"
    t.string  "title"
    t.integer "website_user_id"
end

create_table "users", force: true do |t|
    t.string "name"
    t.string "email"
    t.string "password"
    t.string "password_hash"
    t.string "password_salt"
end

create_table "website_users", force: true do |t|
    t.integer "website_id"
    t.integer "user_id"
    t.integer "role_id"
end

create_table "websites", force: true do |t|
    t.string "name"
    t.string "url"
end

我在这里发生的事情基本上是网站让用户(在网站上工作的团队成员)通过website_user表关联。该表属于角色,因此团队成员将在此网站上拥有特定的作业,最后,任务属于website_user关联,以便您可以换出用户,但任务将与角色和网站保持关联。

我正在考虑进一步扩展它,以便任务将在website_user上关联两次,一次用于分配器,一次用于任务的分配用户。然而,在这一点上,感觉我会在中间的一个大的连接桌上附加很多东西,并且在我的腰带下没有大量的经验,它开始闻起来可能有更好的方式。

如果这一切看起来都不错,您将如何将任务加入到website_user两次,一次是针对分配者,一次是针对分配的?或者,如何重新排列模型关联?

3 个答案:

答案 0 :(得分:1)

我无法在数据库设计中为您提供建议,但您可以使用名为class_name的选项为用户分配两次。您可以在此处阅读更多内容:http://guides.rubyonrails.org/association_basics.html#belongs-to-association-reference

但是你还必须在你的任务模型中添加额外的foreign_key。

我还建议你阅读M. Hartle书中的以下章节,因为它在模型关系之间有很好的解释:https://www.railstutorial.org/book/following_users#cha-following_users

答案 1 :(得分:1)

class Task < ActiveRecord::Base
  belongs_to :assignee, class_name: WebsiteUser, foreign_key:website_user_id
  belongs_to :assigner, class_name: WebsiteUser, foreign_key:assigner_user_id
end

class WebsiteUser < ActiveRecord::Base
  has_many :assigned_tasks, class_name: Task, inverse_of: :assignee, dependent: :destroy, foreign_key: :website_user_id
  has_many :tasks_assigned, class_name: Task, inverse_of: assigner, dependent: :destroy, foreign_key: :assigned_user_id
end

您必须在任务表中添加另一个外键..

只是一个起点,但这应该让你去..

答案 2 :(得分:1)

首先出现的一个简单的解决方案是在任务模型中保留分配者和受让人ID。

迁移 AddAssigneeAssignerToTask

class AddAssigneeAssignerToTask < ActiveRecord::Migration
  change do
    add_reference :task, :assignee, index: true
    add_reference :task, :assigner, index: true
  end
end

belongs_to 添加到任务模型

class Task < ActiveRecord::Base

  belongs_to :assignee, class: 'WebsiteUser'
  belongs_to :assigner, class: 'WebsiteUser'

  has_one :website, through: :assignee
end

修改 WebsiteUser

class WebsiteUser < ActiveRecord::Base

  belongs_to :website
  belongs_to :user
  belongs_to :role

  has_many :assigned_tasks, class_name: 'Task', foreign_key: 'assigner_id'
  has_many :received_tasks, class_name: 'Task', foreign_key: 'assignee_id'
end

之后你就可以像这样使用它了

@website_user.assigned_tasks # => []  
@website_user.received_tasks # => [Task1, Task2]

BUT

如果您想为分配者或受让人添加一些不同的功能,则应考虑使用STIMTI