验证和测试Rails 3关联的完美方法(使用RSpec/Remarkable)?

Jos*_*eim 16 validation ruby-on-rails

我仍然很擅长在Rails 3中测试,我使用RSpec和Remarkable.我已经阅读了很多帖子和一些书籍,但是当我使用该关联的名称时,我仍然有点不确定.

class Project < ActiveRecord::Base
  has_many :tasks
end

class Task < ActiveRecord::Base
  belongs_to :project
end
Run Code Online (Sandbox Code Playgroud)

由于良好的实践,我想保护我的属性免受大规模任务:

class Task < ActiveRecord::Base
  attr_accessible :project  # Or is it :project_id??

  belongs_to :project
end
Run Code Online (Sandbox Code Playgroud)

首先,我想确保一个项目在没有有效任务的情况下永远不会存在:

class Task < ActiveRecord::Base
  validates :project, :presence => true      # Which one is the...
  validates :project_id, :presence => true   # ...right way to go??
end
Run Code Online (Sandbox Code Playgroud)

我还想确保分配的项目或项目ID始终有效:

class Task < ActiveRecord::Base
  validates :project, :associated => true     # Again, which one is...
  validates :project_id, :associated => true  # ...the right way to go?
end
Run Code Online (Sandbox Code Playgroud)

...我需要验证:使用时存在:关联?

非常感谢澄清,似乎经过几个小时的阅读并尝试使用RSpec/Shoulda/Remarkable测试东西我不再看到森林,因为所有的树木了...

Jos*_*eim 11

这似乎是正确的方法:

attr_accessible :project_id
Run Code Online (Sandbox Code Playgroud)

你也不必放在:project那里!无论如何都可以做到task.project=(Project.first!)

然后:project_id使用以下内容检查是否存在(使用:project_id时也设置task.project=(...)):

validates :project_id, :presence => true
Run Code Online (Sandbox Code Playgroud)

现在确保关联项目的有效性如下:

validates :project, :associated => true
Run Code Online (Sandbox Code Playgroud)

所以:

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!
Run Code Online (Sandbox Code Playgroud)

遗憾的是,通过t.project_id =它分配ID时,不会检查此特定ID是否确实存在.您必须使用自定义验证或使用验证存在GEM来检查这一点.

要使用带有Remarkable匹配器的RSpec测试这些关联,请执行以下操作:

describe Task do
  it { should validate_presence_of :project_id }
  it { should validate_associated :project }
end
Run Code Online (Sandbox Code Playgroud)

  • 哇,这让人大开眼界.我用Rails 3.2.3获得了意想不到的结果.试试这个.在Task模型中,添加`validates:project,:presence => true`但不添加`:associated`验证.在控制台中,使用project_id = 999创建一个新任务,并检查它是否为".valid?".Rails在项目表中查找记录,然后(可能是因为找不到它并且project_id仍为零),验证失败.现在将验证更改为`validates:project_id,:presence => true`.Rails不读取项目,验证成功.添加`:associated`并且验证*仍然*成功. (2认同)