【问题标题】:Rails Joining multiple models on a single tableRails 在一个表上连接多个模型
【发布时间】:2015-04-20 17:33:01
【问题描述】:

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

数据库:

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 两次,一次用于分配者,一次用于分配?或者,如何重新排列模型关联?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案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 添加到 Task 模型中

    class Task < ActiveRecord::Base
    
      belongs_to :assignee, class: 'WebsiteUser'
      belongs_to :assigner, class: 'WebsiteUser'
    
      has_one :website, through: :assignee
    end
    

    修改网站用户

    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]
    

    但是

    如果您想为assigner 或assignee 添加一些不同的功能,您应该考虑使用STIMTI

    【讨论】:

      【解决方案2】:
      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
      

      你将不得不在你的任务表中添加另一个外键..

      只是一个起点,但这应该能让你继续前进..

      【讨论】:

        【解决方案3】:

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

        但您还必须向 Tasks 模型添加额外的 foreign_key。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多