rails,rspec,shoulda validate_presence_of因两次调用setter而失败

时间:2013-04-23 17:29:37

标签: ruby-on-rails rspec2 shoulda

在具有公司模型的简单rails应用程序中

class Company < ActiveRecord::Base

  # Attributes
  attr_accessible :name

  validates_presence_of :name

  def name=(s)
    self[:name] = s.upcase
  end
end

运行以下spec文件时。它失败。

require 'spec_helper'

describe Company do

  before :each do
    @company = Company.new({name: 'my_company'})
  end

  it "should validate presence of name" do
    @company.should validate_presence_of(:name)
  end

end

调试显示name =(s)方法被调用两次,一次使用&#39; my_company&#39;一次只有零。

我不明白为什么第二次电话会发生在尼尔身上。  这是使用的宝石:

gem 'rails', '3.2.13'
gem 'mysql2' 

group :development, :test do
  gem 'rspec-rails', '2.11.0' 
  gem 'shoulda-matchers', :require => false
end

2 个答案:

答案 0 :(得分:1)

  • 应该用来写一个衬里规格,如文件中提到的那样 它{should validate_presence_of(:name)}
    它{should validate_presence_of(:name).with_message(/不是可选的/)}

    因此,您可以按照以下更具可读性的方式编写规范:

    describe 'validations' do  
     it {should validate_presence_of(:name)}  
     end
  • 关于名称字段的两个作业的问题:

    1. 首先分配在您的规范之前(:每个)块和
    2. 是否存在验证程序会尝试为您指定要验证状态的所有属性指定nil值,如果您的模型为:名称。 您的重写名称=方法发生在此nil值,并且它会引发错误,因为它无法取消nil。上面显示的一个衬垫规格也会因同样的原因而失效。要解决此问题,您可以更改setter方法以执行 s.try(:upcase)。因此它可以处理零值并且不会导致任何问题。

答案 1 :(得分:0)

原因可能是你在新的name方法中提到了name

最好使用write_attribute方法作为您引用的文档。

将其读作:

 def name=(s)
   write_attribute(:name, s.upcase)
 end