如何在rails中有很多通过创建关系
Posted
技术标签:
【中文标题】如何在rails中有很多通过创建关系【英文标题】:how can create relation with has many through in rails 【发布时间】:2021-11-11 06:49:15 【问题描述】:我有 3 个模型用户项目错误。我想通过创建多对多关系。我在模型中创建关系我不知道它是否正确,用户有用户类型列,它是枚举类型用户类型包含开发人员、经理、QA
user.user_type.manager belong to many project it has one to many relation
user.user_type.developer has many project and many project belong to developer. it has many to many realtion
project has many bugs and bugs belong to project
developer has many bugs and many bugs belong to developer
错误模型
class Bug < ApplicationRecord
belongs_to :project
has_many :developers, -> where user_type: :Developer , class_name: 'User', through: :project, source: :bugs
end
项目模型
class Project < ApplicationRecord
has_many :bugs, dependent: :delete_all
has_many :developers, -> where user_type: :Developer , class_name: 'User', through: :users, source: :project
has_many :users //it belong to manager_id
end
用户模型
class User < ApplicationRecord
enum user_type: %i[Manager Developer QA]
has_many :projects
has_many :bugs
end
developer_bug 模型
class DevelopersBug < ApplicationRecord
has_many :bugs
has_many :users
end
project_developer 模型
class ProjectsDeveloper < ApplicationRecord
has_many :projects
has_many :users
end
【问题讨论】:
使用snake_case
作为您的枚举键。 %i[manager developer qa]
。 ActiveRecord::Enum
基于键生成方法,因此您将获得 User.Developer
,这是非常非常规的并且会导致错误。例如,如果您在没有显式使用self
的情况下调用该方法,解析器将认为它是一个常量。 github.com/rubocop/…
【参考方案1】:
这个
has_many :developers, -> where user_type: :Developer ,
class_name: 'User',
through: :users,
source: :project
不是你想的那样。它的意思是:
我已经有一个关联“用户”。用户有一个关联“项目”。
请配置一个关联,使两个 JOIN 都加入,并为我提供与关联用户关联的项目列表。
这个关联将被命名为“开发者”并且属于“用户”类的对象。
您可以看到这些说明是如何不一致的。这个
has_many :projects, through: :users, source: :project
将通过跳过用户来定义相关项目的列表。
另一方面,这个:
has_many :developers, -> where user_type: :Developer , class_name: 'User'
将与所有用户的子集定义一个直接 has-many 关联。
根据您的描述,您的数据模型似乎错误,也许这样会更好:
class User < ApplicationRecord
has_many :managed_projects, inverse_of: :manager, class_name: 'Project'
has_and_belongs_to_many :projects
has_many :bugs
end
class Project < ApplicationRecord
belongs_to :manager, class_name: 'User', inverse_of: :managed_projects
has_and_belongs_to_many :users
has_many :bugs
end
class Bug < ApplicationRecord
belongs_to :user
belongs_to :project
end
您的架构应包括三个表,以及一个额外的多对多连接表 projects_users
,其中包含用户和项目的外键。
【讨论】:
但我想将错误和开发人员的 ID 存储到单独的表中。我该怎么做呢 您能否改写一下,以便我了解您需要实现的目标?在我的建议中,bug 的 id 存储在bugs
表中,开发人员的 id 存储在 users
表中。【参考方案2】:
正如重写已经在他的出色回答中指出的那样,您的数据模型存在缺陷。你想要的是一个连接用户和项目的连接表:
class User < ApplicationRecord
has_many :project_roles
has_many :projects, through: :project_roles
end
class ProjectRole < ApplicationRecord
belongs_to :user
belongs_to :project
end
class Project < ApplicationRecord
has_many :users
has_many :projects, through: :project_roles
end
如果您想在项目中为用户提供特定角色,您可以将枚举添加到连接表中,这就是它开始变得棘手的地方,所以请耐心等待:
class ProjectRole < ApplicationRecord
enum roles: [:manager, :developer, :qa]
belongs_to :user
belongs_to :project
end
class User < ApplicationRecord
has_many :project_roles
has_many :projects, through: :project_roles
has_many :project_roles_as_manager,
-> manager , # short for `where(role: :manager)`
class_name: 'ProjectRole'
has_many :projects_as_manager,
class_name: 'Project',
through: :project_roles_as_manager,
source: :project
has_many :project_roles_as_developer,
-> developer ,
class_name: 'ProjectRole'
has_many :projects_as_developer,
class_name: 'Project',
through: :project_roles_as_developer,
source: :project
# ...
end
这定义了具有默认范围的关联,然后通过该关联加入。然后你会在关联的另一端做同样的事情:
class Project < ApplicationRecord
has_many :users
has_many :projects, through: :project_roles
has_many :manager_project_roles,
-> manager ,
class_name: 'ProjectRole'
has_many :managers,
through: :manager_project_roles,
source: :user
# ...
end
当然,这是很多重复,您可以通过循环 ProjectRoles.roles.keys
并动态定义关联来减少这些重复。
这是一种非常灵活的建模方式,它对领域的假设尽可能少。例如,它允许一个项目有多个经理,它允许用户在不同的项目中拥有不同的角色。
如果您想像通常在跟踪器中处理问题那样对“错误”建模,您可以为错误创建一个表并为分配创建一个连接表:
class Bug < ApplicationRecord
belongs_to :project
has_many :bug_assignments
has_many :users, through: :bug_assignments
end
class BugAssignment < ApplicationRecord
has_one :project, through: :bug
belongs_to :bug
belongs_to :user
end
class User < ApplicationRecord
# ...
has_many :bug_assignments
has_many :bugs
end
【讨论】:
不错的方法,但我觉得它对 OP 来说有点太复杂了 :) @rewritten 我同意它有点太复杂了。但它是一种在与现实接触中幸存下来的模型。以上是关于如何在rails中有很多通过创建关系的主要内容,如果未能解决你的问题,请参考以下文章
在 ruby on rails 中以一对多关系创建新记录