对于在Rails3中进行测试,我还是个新手,我使用的是RSpec和Remarkable。我已经阅读了很多帖子和一些书,但我仍然不确定何时使用协会的名称,何时使用它的ID。
class Project < ActiveRecord::Base
has_many :tasks
end
class Task < ActiveRecord::Base
belongs_to :project
end
由于良好的实践,我希望保护我的属性不受批量赋值的影响:
class Task < ActiveRecord::Base
attr_accessible :project # Or is it :project_id??
belongs_to :project
end
首先,我想要确保一个没有有效任务的项目是存在的:
class Task < ActiveRecord::Base
validates :project, :presence => true # Which one is the...
validates :project_id, :presence => true # ...right way to go??
end
我还希望确保分配的项目或项目ID始终有效:
class Task < ActiveRecord::Base
validates :project, :associated => true # Again, which one is...
validates :project_id, :associated => true # ...the right way to go?
end
...and使用:associated时是否需要验证:presence??
非常感谢你的澄清,似乎经过几个小时的阅读和尝试使用RSpec/Shoulda/ clarifying测试后,我看不到森林了,因为所有的树都在……
发布于 2012-07-04 20:49:39
这似乎是正确的方法:
attr_accessible :project_id
你不需要把:project
也放在那里!无论如何,做task.project=(Project.first!)
都是可能的
然后使用以下命令检查:project_id
是否存在(使用task.project=(...)
时也会设置:project_id
):
validates :project_id, :presence => true
现在,确保关联的项目有效,如下所示:
validates :project, :associated => true
所以:
t = Task.new
t.project_id = 1 # Value is accepted, regardless whether there is a Project with ID 1
t.project = Project.first # Any existing valid project is accepted
t.project = Project.new(:name => 'valid value') # A new valid project is accepted
t.project = Project.new(:name => 'invalid value') # A new invalid (or an existing invalid) project is NOT accepted!
有点遗憾的是,当通过t.project_id =
分配ID时,不会检查这个特定的ID是否真的存在。您必须使用自定义验证或使用Validates Existence GEM对此进行检查。
要使用RSpec和出色的匹配器来测试这些关联,请执行以下操作:
describe Task do
it { should validate_presence_of :project_id }
it { should validate_associated :project }
end
发布于 2012-07-04 18:48:18
validates :project, :associated => true
validates :project_id, :presence => true
如果您希望确保存在关联,则需要测试用于映射关联的外键是否存在,而不是关联的对象本身。http://guides.rubyonrails.org/active_record_validations_callbacks.html
attr_accessible :project_id
发布于 2013-03-05 04:01:20
编辑:假设关联不是可选的...
我能让它彻底验证的唯一方法是:
validates_associated :project
validates_presence_of :project_id,
:unless => Proc.new {|o| o.project.try(:new_record?)}
validates_presence_of :project, :if => Proc.new {|o| o.project_id}
第一行验证关联的Project是否有效(如果有)。第二行坚持project_id
存在,除非关联的项目存在并且是新的(如果它是一个新的记录,那么它还没有ID )。第三行确保如果存在ID,则项目存在,即,如果关联的项目已被保存。
如果您将保存的项目分配给ActiveRecord,project
将为该任务分配一个project_id
。如果您将一个未保存的/新的项目分配给project
,它将把project_id
留空。因此,我们希望确保project_id
存在,但仅在处理保存的项目时;这是在上面的第二行中完成的。
相反,如果您为代表真实项目的project_id
分配一个数字,ActiveRecord将使用相应的项目对象填充project
。但是,如果您分配的ID是假的,它会将project
保留为空。因此,上面的第三行确保如果填充了project_id
,我们就有了一个project
--如果您提供了一个伪造的ID,这将失败。
请参阅测试这些验证的RSpec示例:https://gist.github.com/kianw/5085085
https://stackoverflow.com/questions/11327390
复制相似问题