我有两个通过has_many
关系关联的模型。 E.g。
class Newspaper < ActiveRecord::Base
has_many :articles
end
class Article < ActiveRecord::Base
belongs_to :newspaper
validates :uid, presence: true,
uniqueness: { case_sensitive: true }
end
报纸每天更新几次,但我们只想构建和添加尚未存在的协会的文章。以下代码是我实现这一目标的第一步。
new_articles.each do |article|
unless newspaper.articles.exists? uid: article.uid
newspaper.articles.build(uid: article.uid)
end
end
报纸对象是新的和未保存的,或者此时通过现有关系检索。
我的测试表明我能够使用上面的代码在报纸上添加两篇具有相同UID的文章,这显然不是我想要的。
我觉得我的当前代码会在保存时导致验证失败 ,因为验证会查看整个文章表中的唯一性,而不是 >协会
我正在努力理解的是exists?
方法在这种情况下的表现(以及为什么它没有像我计划的那样保存我的培根)。我正在使用FactoryGirl来制作一份报纸,添加一篇文章然后模拟包含一篇文章的更新,该文章与我已经添加的文章具有相同的uid。如果代码有效,我应该只获得一篇相关文章,但我得到两篇。使用build
或create
没有任何区别,因此文章记录是否已存在于数据库中似乎不会改变结果。
任何人都可以阐明我如何能够达到理想的结果或为什么exists?
方法没有达到预期效果?
由于
答案 0 :(得分:0)
关联exists?
实际上会根据关联创建范围查询。这就是您现有文章过滤器不起作用的原因。
unless newspaper.articles.exists? uid: article.uid
# `articles.exists?` here will produce this if the newspaper is new
# ... WHERE "articles"."newspaper_id" IS NULL AND "articles.uid" = '<your uid>'
# and this, if the newspaper is persisted (with an id of 1)
# ... WHERE "articles"."newspaper_id" = 1 AND "articles.uid" = '<your uid>'
新报纸的情况显然是错误的,因为它只返回带有nil
报纸ID的文章。但持续存在的情况也可能是不受欢迎的,因为它仍然不必要地过滤报纸ID,当你真正担心的是UID是独特的。
相反,您可能只想反对Article
,而不是通过关联确定exists?
,例如:
unless Article.exists? uid: article.uid
关于你的其他问题:
这似乎是一个FactoryGirl问题,其中create方法没有像我在irb中那样创建数据库条目。
FactoryGirl.create
仍应遵守验证。看看你的测试可能会有所帮助。