正确的方法是带有归属关系关联的validates_presence_of

|| 我正在研究validates_presence_of的实际工作方式。假设我有两个模型
class Project < ActiveRecord::Base
  [...]
  has_many :roles
end
class Role < ActiveRecord::Base
  validates_presence_of :name, :project

  belongs_to :project
end
我希望角色始终属于现有项目,但是从此示例中我发现这可能导致将无效(孤立)角色保存到数据库中。因此,正确的方法是将ѭ2插入我的角色模型中,并且似乎起作用,即使我认为从语义上更有效地验证项目的存在而不是项目ID。 除此之外,我还想如果我只验证project_id的存在,就可以放置一个无效的id(对于一个不存在的项目),因为默认情况下,AR不会向迁移添加完整性检查,即使我手动添加了它们DB不支持它们(即带有MyISAM或sqlite的MySQL)。这个例子证明
# with validates_presence_of :name, :project, :project_id in the role class
Role.create!(:name => \'foo\', :project_id => 1334, :project => Project.new)
  AREL (0.4ms)  INSERT INTO \"roles\" (\"name\", \"project_id\") VALUES (\'foo\', NULL)
+----+------+------------+
| id | name | project_id |
+----+------+------------+
| 7  | foo  |            |
+----+------+------------+
当然,我不会编写这样的代码,但是我想防止在DB中出现这种错误的数据。 我想知道如何确保角色始终具有(真实和保存的)项目关联。 我找到了validates_existence宝石,但是除非绝对必要,否则我不希望不在项目中添加宝石。 有什么想法吗? 更新资料 在迁移中的project_id列中添加
validates_presence_of :project
并在其中添加
:null => false
似乎是一种更干净的解决方案。     
已邀请:
        Rails将尝试在id上进行查找,如果找不到带有id的对象,则会添加验证错误。
class Role < AR::Base
  belongs_to :project
  validates_presence_of :project, :name
end


Role.create!(:name => \"admin\", :project_id => 1334)# Project 1334 does not exist
# => validation error raised
我看到您的问题还想处理提供author对象但是新对象而不是在db中的情况。在这种情况下,状态检查不起作用。会解决。
Role.create!(:name => \"admin\", :project => Project.new) # Validation passes when it shouldn\'t.
更新: 在某种程度上,您可以通过对关联的:project进行验证来减轻传递虚拟新对象的影响。
class Role < ActiveRecord::Base
  belongs_to :project
  validates_presence_of :project
  validates_associated :project
end
如果
Project.new.valid?
为假,那么
Role.create!(:name => \"admin\", :project => Project.new)
也将引发错误。但是,如果“ 9”为true,则以上内容将在保存时创建一个项目对象。 使用
validates_associated :project
对您有帮助吗?     
        我尝试了很多验证器组合,但最干净的解决方案是使用validates_existence gem。这样我就可以编写这样的代码
r = Role.new(:name => \'foo\', :project => Project.new) # => #<Role id: nil, name: \"foo\", project_id: nil, created_at: nil, updated_at: nil> 
r.valid? # => false 
r.errors # => {:project=>[\"does not exist\"], :project_id=>[\"does not exist\"]} 
所以我的最终模型很简单
class Role < ActiveRecord::Base
  belongs_to :project
  validates_existence_of :project
  # or with alternate syntax
  validates :project, :existence => true
  [...]
end
使用db验证和Aditya解决方案(即:迁移中的:null => false以及模型中的validates_presence_of:project),当project_id为null时,
Role#valid?
将返回true,
Role#save
将在数据库级别引发异常。     

要回复问题请先登录注册