我试图弄清楚如何在使用 << collection operator. 更新集合时正确验证模型集合 在我们的遗留应用程序(Rails 3.2.1)中,我发现 platform_collection_obj.platforms 使用 << operator
更新例子:
collection.platforms << new_platform
在研究如何验证平台集合中的每个 平台 是否具有适当的数据时,我发现我应该使用自定义验证功能。所以我尝试将 each_platform_branch_id 验证函数添加到 PlatformCollections 模型。然而,我在测试中(通过 rails 控制台)发现验证没有被触发。
在阅读Has-Many-Association-Collection Info时,我遇到了这个
通过将对象的外键设置为集合的主键,将一个或多个对象添加到集合中。请注意,此操作会立即触发更新 SQL,而无需等待对父对象的保存或更新调用,除非父对象是新记录。这也将运行关联对象的验证和回调。
此摘录表明使用 << 在 collection.platforms 上执行更新不会触发父验证,在本例中为 PlatformCollection:each_platform_branch_id 验证函数。我知道手动执行 collection.save 会触发验证,但为时已晚 b/c << 已经更新了数据库。
所以重申这个问题是: 每当使用 << collection operator?
更新集合时,如何正确验证具有多个模型的集合平台收藏模型
class PlatformCollection < ActiveRecord::Base
belongs_to :tezt
has_many :platform_collection_platforms, :order => "platform_collection_platforms.default DESC"
has_many :platforms, :through => :platform_collection_platforms, :order => "platform_collection_platforms.default DESC"
def each_platform_branch_id
platforms.each do |p|
if p.branch_id != @branch.id
err_msg = "Invalid Platform: #{p.to_json} for PlatformCollection: #{self.to_json}. " \
"Expected Branch: #{@branch.id}, Actual Branch: #{p.branch_id}"
errors.add(:platform, err_msg)
end
end
end
平台模型
class Platform < ActiveRecord::Base
attr_accessible :name
belongs_to :branch
has_many :platform_collection_platforms
has_many :platform_collections, :through => :platform_collection_platforms
在这里完全不使用
<<
运算符 (collection.platforms << new_platform
),也许最好显式创建 JOIN 记录?
即类似的东西:
collection.platform_collection_platforms.build(
platform_collection: collection,
platform: new_platform
)
(我的天哪,这是一组令人困惑的名字!!)
现在您可以完全控制
validate
.
您可以使用 关联回调 在对象添加到关联(或从关联中删除)之前或之后执行检查或调用方法。比如像这样:
has_many :platforms, through: :platform_collection_platforms,
before_add: :check_branch_id
private
def check_branch_id(platform)
throw(:abort) if platform.branch_id != branch_id
end
顺便说一句。 Ruby on Rails 3.2.1 发布于 11 多年前,大约 7 年前达到生命周期结束,并且有一个长的众所周知的安全漏洞列表。我强烈建议将该应用程序更新到更新和更安全的版本。