如何为一个成员强制设置 has_many_through 关联?

Posted

技术标签:

【中文标题】如何为一个成员强制设置 has_many_through 关联?【英文标题】:How to make a has_many_through association mandatory for one member? 【发布时间】:2013-12-16 22:09:43 【问题描述】:

我有以下型号:

class City < ActiveRecord::Base
  has_many :cities_regions_relationships
  has_many :regions, through: :cities_regions_relationships
end

class Region < ActiveRecord::Base
  has_many :cities_regions_relationships
  has_many :cities, through: :cities_regions_relationships
end

class CitiesRegionsRelationship < ActiveRecord::Base
  belongs_to :city
  belongs_to :region

  validates :city_id, presence: true
  validates :region_id, presence: true
end

我想要的是,如果没有与地区相关联的城市,就无法创建城市。但是,在尝试这样做之前,我必须能够在尚未保存的城市上建立关系。

我在控制台中试过这个(已经创建了一个区域)

c = City.new(name: "Test")
c.cities_region_relationship.build(region_id: Region.first.id)
c.save

但是,这会失败,因为关系没有 city_id(这很正常,因为我还没有保存城市,它没有 ID)。

我可以尝试其他方法,但我总是会遇到同样的问题:如何在尚未保存在数据库中的新对象上创建关系?

如果您对我最初的问题(强制城市至少有一个区域)有其他完全不同的解决方案,请不要犹豫,提出完全不同的建议。

【问题讨论】:

一个city可以有多个regions吗? @AbM 是的。否则我可以使用has_many 和belongs_to,但不幸的是我的模型不是那么简单:( 查看SO post 【参考方案1】:

您不需要构建cities_region_relationship。通过将region_ids 传递给一个新的City 实例,这将为您创建cities_region_relationship

你可以在控制台试试:

c = City.new(name: "Test", region_ids: [an array of existing region ids])
c.save

对于验证,您可以定义一个新的验证方法来检查 self.regions.blank? 是否像我上面评论中的 SO 帖子中提到的那样。

【讨论】:

不幸的是,这不起作用:c.errors 给了我#&lt;ActiveModel::Errors:0x007ff163ab7870 @base=#&lt;City id: nil, name: "Test", created_at: nil, updated_at: nil&gt;, @messages=:cities_regions_relationships=&gt;["is invalid"]&gt;。如您所见,该关系没有 city_id 并且无效。 我忘了提到要删除CitiesRegionsRelationship 中的验证,即您不需要validates :city_id, presence: truevalidates :region_id, presence: true。您的验证仅在 City 模型中进行,以检查实例是否具有不是 blankregions 数组

以上是关于如何为一个成员强制设置 has_many_through 关联?的主要内容,如果未能解决你的问题,请参考以下文章

如何为一些子成员设置卡片视图的角半径?

如何为 iTunes 连接提供强制更新?

如何为stream任务的日志成员设置SBT logLevel?

如何为命令行强制使用PHP版本?

如何为 .NET 项目自定义强制代码样式规则

如何为 .NET 项目自定义强制代码样式规则 #yyds干货盘点#