Frage

In a simple rails app with a company model

class Company < ActiveRecord::Base

  # Attributes
  attr_accessible :name

  validates_presence_of :name

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

When the following spec file is run. it fails.

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

Debugging showed that the name=(s) method is called twice, once with 'my_company' and once with nil.

I don't get why a second call happen with nill. here are the gems used:

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

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

Lösung

  • Shoulda is meant to be used to write one liner specs as mentioned in the documentation like
    it { should validate_presence_of(:name)}
    it { should validate_presence_of(:name).with_message(/is not optional/) }

    So you can write your spec in more readable fashion as follows:

    describe 'validations' do  
     it {should validate_presence_of(:name)}  
     end
  • Regarding your question of two assignments for the name field :

    1. First assignment is done in your spec's before(:each) block and
    2. Shoulda presence validator tries to assign nil value for all attributes you specified to be validated for presence, which in case of your model is :name.
      Your overridden name= method takes place for this nil value, and it raises an error as it can not upcase nil. One liner spec shown above will also fail for the same reason. To solve this problem you can change you setter method to do s.try(:upcase). So it can work on nil values and won't cause any problem.

Andere Tipps

The reason may be you mentioned name in the new name method.

Better to use write_attribute method as the doc you referred.

To read it as:

 def name=(s)
   write_attribute(:name, s.upcase)
 end
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top