在初始化期间设置属性

时间:2014-09-02 18:55:59

标签: ruby-on-rails-4

模型是:

class Persona < ActiveRecord::Base
  before_save :make_downcase_name
  after_initialize :make_downcase_name
  validates :name, presence: true, length: { maximum: 50 }
  validates :downcase_name, uniqueness: { case_sensitive: false }

  private

    def make_downcase_name
      if name != nil
        self.downcase_name ||= name.downcase
      end
    end
end

此测试失败:

before do
  @persona = Persona.new(name: "Bazman")
end

subject { @persona }

describe "name with mixed case" do
  let(:mixed_case_name) { "TeRRy" }
  it "should be saved as all lower-case" do
    @persona.name = mixed_case_name
    @persona.save
    expect(@persona.reload.downcase_name).to eq mixed_case_name.downcase
  end
end

错误消息:

预计:“特里”

得到:“巴兹曼”

所以这意味着在测试@ persona.save时,before_save回调不会将TeRRy的downcase_name更改为terry,所以行

self.downcase_name ||= name.downcase

失败了,但我不明白为什么。

1 个答案:

答案 0 :(得分:1)

由于downcase_name的工作方式,

make_downcase_name未更新为新名称的小写版本。

self.downcase_name ||= name.downcase

此行可以解释为:如果downcase_name为假(nilfalse),则将其设置为name.downcase。否则,不管它。

这里有两种选择。您的规范是正确的,并且在分配新名称时应更新downcase_name,或者您的模型是正确的,并且downcase_name在首次分配后永远不会更改。

选项1:规范是正确的

在这种情况下,您需要修复模型:

def make_downcase_name
  return unless name

  self.downcase_name = name.downcase
end

那就是它!

选项2:模型是正确的

如果是这样,您需要确保在规范中创建新的Persona。首先,让我们对您的规范进行一次小的重构,以使用let声明变量,而不是使用实例变量:

let(:persona) { Persona.new(name: 'Bazman' }
subject       { persona }

describe "name with mixed case" do
  let(:mixed_case_name) { "TeRRy" }

  it "should be saved as all lower-case" do
    persona.name = mixed_case_name
    persona.save
    expect(persona.reload.downcase_name).to eq mixed_case_name.downcase
  end
end

对于name with mixed case方案,您现在可以轻松创建新的Persona实例:

let(:persona) { Persona.new(name: 'Bazman') }
subject       { persona }

describe "name with mixed case" do
  let(:mixed_case_name) { "TeRRy" }
  let(:persona)         { Persona.new }

  it "should be saved as all lower-case" do
    persona.name = mixed_case_name
    persona.save
    expect(persona.downcase_name).to eq mixed_case_name.downcase
  end
end