validates_ presence_of与belongs_to的关联,以正确的方式 [英] validates_presence_of with belongs_to associations, the right way
问题描述
我在研究如何validates_ presence_of实际工作。假设我有两个型号
I'm investigating on how validates_presence_of actually works. Suppose I have two models
class Project < ActiveRecord::Base
[...]
has_many :roles
end
和
class Role < ActiveRecord::Base
validates_presence_of :name, :project
belongs_to :project
end
我希望它这样的角色总是属于现有的项目,但我只是发现了从<一个href="http://stackoverflow.com/questions/2859384/rails-validate-$p$psence-of-parent-id-in-has-many-association/3017982#3017982">this例如的,这可能会导致保存到数据库无效(孤立的)角色。因此,正确的做法是插入 validates_ presence_of:PROJECT_ID
在我的榜样,它似乎工作,即使我认为语义上有更多的意义验证项目,而不是项目ID的presence。
I want it so that role always belongs to an existing project but I just found out from this example that this could lead to invalid (orphaned) roles saved into the db. So the right way to do that is to insert the validates_presence_of :project_id
in my Role model and it seems to work, even if I think that semantically has more sense to validate the presence of a project instead of a project id.
除此之外,我想,我可以把无效的ID(对于不存在的项目),如果我只是验证PROJECT_ID的presence,因为默认情况下,AR不会增加完整性检查迁移,即使我将它们添加手动某些数据库不支持他们(即用的MySQL的MyISAM或源码)。这个例子证明了
Besides that I was thinking that I could put an invalid id (for a non existing project) if I just validate the presence of project_id, since by default AR doesn't add integrity checks to migrations, and even if I add them manually some DB does not support them (i.e. MySQL with MyISAM or sqlite). This example prove that
# 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 | |
+----+------+------------+
当然,我不会写code这样的,但我想prevent这种错误数据的数据库。
Of course I won't write code like this, but I want to prevent this kind of wrong data in DB.
我不知道如何保证一个角色总是有关联的(实际和保存)项目。
I'm wondering how to ensure that a role ALWAYS has a (real and saved) project associated.
我发现 validates_existence 的宝石,但我preFER不添加宝石到我的项目除非是绝对必要的。
I found the validates_existence gem, but I prefer to not add a gem into my project unless is strictly necessary.
对此有何想法?
更新
validates_ presence_of:项目
并添加:空=&GT;假
在迁移PROJECT_ID列似乎是一个清晰的解决方案。
validates_presence_of :project
and adding :null => false
for the project_id column in the migration seems to be a cleaner solution.
推荐答案
我尝试了很多验证的组合,但干净的解决方案是使用的 validates_existence 宝石。随着我可以写code这样
I tried a lot of combinations of validators, but the cleanest solution is to use the validates_existence gem. With that I can write code like this
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"]}
所以,我最终的模型很简单,只要
So my final model is as simple as
class Role < ActiveRecord::Base
belongs_to :project
validates_existence_of :project
# or with alternate syntax
validates :project, :existence => true
[...]
end
通过数据库验证加阿迪亚解决方案(即:空=>假的迁移和validates_ presence_of:项目模型)?角色#有效
返回真实和角色#保存
时PROJECT_ID为null,将引发一个例外,在数据库级别。
With db validation plus Aditya solution (i.e. :null => false in the migration and validates_presence_of :project in the model) Role#valid?
will return true and Role#save
will raise an exception at database level when project_id is null.
这篇关于validates_ presence_of与belongs_to的关联,以正确的方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!