首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >验证和测试Rails3关联的完美方法(使用RSpec/卓越)?

验证和测试Rails3关联的完美方法(使用RSpec/卓越)?
EN

Stack Overflow用户
提问于 2012-07-04 18:36:55
回答 4查看 13.5K关注 0票数 16

对于在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测试后,我看不到森林了,因为所有的树都在……

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 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
票数 11
EN

Stack Overflow用户

发布于 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
票数 4
EN

Stack Overflow用户

发布于 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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11327390

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档