英文:
Create Record With "has_many_through" Association – Ruby on Rails
问题
我有一个has_many_through
关联,其中User
通过ProjectUser
拥有许多Project
。Rails具有一些魔法,可以使用以下方式更新此关系:
u = User.first
u.update(project_ids: [...])
是否有一种干净的方法可以使用create
来做同样的事情?
运行User.create(name: ..., project_ids: [...])
会失败,错误信息为Validation failed: Project users is invalid
。
我怀疑这是因为Rails在创建User
记录之前尝试创建ProjectUser
记录,并在连接表上进行了一些内置验证,以验证连接的两侧是否已经存在。ProjectUser
模型没有自定义验证。
class ProjectUser < ApplicationRecord
belongs_to :project
belongs_to :user
end
是否有一种简单的方法来解决这个问题?
英文:
I have a has_many_through
association where User
s have many Project
s through ProjectUser
s. Rails has some magic that allows updating this relationship with:
u = User.first
u.update(project_ids: [...])
Is there a clean way to do the same thing with create
?
Running User.create(name: ..., project_ids: [...])
fails with Validation failed: Project users is invalid
.
I suspect this is because Rails tries to create the ProjectUser
record before creating the User
record and has some built-in validation on join tables to validate that both sides of the join already exist. The ProjectUser
model has no custom validation.
class ProjectUser < ApplicationRecord
belongs_to :project
belongs_to :user
end
Is there a simple way to get around this?
答案1
得分: 3
Active Record 支持大多数具有标准名称的关联的自动识别。然而,Active Record 不会自动识别包含 :through 或 :foreign_key 选项的双向关联。(您可以在这里查看)
因此,您必须明确定义 inverse_of
。
class Project < ApplicationRecord
has_many :project_users, foreign_key: :project_id, inverse_of: :project
has_many :users, through: :project_users
end
class User < ApplicationRecord
has_many :project_users, foreign_key: :user_id, inverse_of: :user
has_many :projects, through: :project_users
end
class ProjectUser < ApplicationRecord
belongs_to :project
belongs_to :user
end
英文:
Active Record supports automatic identification for most associations with standard names. However, Active Record will not automatically identify bi-directional associations that contain the :through or :foreign_key options. (You can check here)
So you have to define inverse_of
explicitly.
class Project < ApplicationRecord
has_many :project_users, foreign_key: :project_id, inverse_of: :project
has_many :users, through: :project_users
end
class User < ApplicationRecord
has_many :project_users, foreign_key: :user_id, inverse_of: :user
has_many :projects, through: :project_users
end
class ProjectUser < ApplicationRecord
belongs_to :project
belongs_to :user
end
答案2
得分: 0
通常人们使用hmt(而不是has_and_belongs_to_many
)是因为他们有其他字段需要在关联表中填充,因此人们通常使用关联表创建模型记录的三元组,例如。
ProjectUser.create! the_extra_field: "Foo", user: User.create!(name: "Jim"), project: Project.create!(title: "Project X")
显然,如果您已经有现有的User
或Project
,那么您会使用它们而不是创建新的。
英文:
Generally people use hmt (instead of has_and_belongs_to_many
) because they have other fields that they're interested in populating in the join table, hence people usually create the triplet of model records using the join table, eg.
ProjectUser.create! the_extra_field: "Foo", user: User.create!(name: "Jim"), project: Project.create!(title: "Project X")
Obviously if you already have an existing User
or Project
then you'd use those instead of creating new ones.
答案3
得分: -2
我相信你需要使用 accepts_nested_attributes_for
class User < ApplicationRecord
has_many :project_users
has_many :projects, through: :project_users
accepts_nested_attributes_for :projects
end
这应该能帮助你创建带有关联项目的用户,就像你期望的那样
User.create(name: 'John', project_ids: [...])
英文:
I believe that you need to use accepts_nested_attributes_for
class User < ApplicationRecord
has_many :project_users
has_many :projects, through: :project_users
accepts_nested_attributes_for :projects
end
That must help you to create users with associated projects like you expected
User.create(name: 'John', project_ids: [...])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论