2013-01-14 44 views
0

我已經閱讀了大多數有關類似問題的答案,但還沒有找到解決方案。代碼如下:從RSpec調用時未激發ActiveRecord before_validation回調示例

設置

class Person < ActiveRecord::Base 
    # Other inconsequential code 
    # ... 
    has_and_belongs_to_many :roles 
    before_validation: attach_roles 
    # ... 
    def attach_roles 
    roles << Role.default if roles.blank? 
    end 
end 

class Role < ActiveRecord::Base 

    has_and_belongs_to_many: people 

    def self.default 
    # 
    # Get default role 
    # 
    end 

end 

測試

require 'spec_helper' 

RSpec.configure do |config| 
    config.include FactoryGirl::Syntax::Methods 
end 

describe Person do 

    context "constructor" do 

    it "creates a valid Person" do 
     person = build(:person) 
     person.should_receive(:attach_roles) # This works 
     person.valid? 
     puts person.roles.inspect # Returns [] 
    end  

    it "creates a another valid Person" do 
     person = build(:person) 
     person.valid? 
     person.should be_valid # This fails 
     puts person.roles.inspect # Returns [] 
    end 

    end 


end 

問題

attach_roles回調似乎並沒有被調用。然而should_receive斷言真正

在控制檯

p = FactoryGirl.build(:person) 
p.roles # [] 
p.valid? # true 
p.roles # [<Role>] 

會有人能夠解釋這個嗎?

附註:任何其他想法都可以實現創建默認角色。

信封

  • 3.2.1
  • 紅寶石1.9.3
  • rspec的2.12.0
  • factory_girl 4.1.0
+0

嘗試:'self.roles <<' – apneadiving

+0

沒有。不起作用。你有這個建議的具體原因嗎?因爲只有角色可以用作訪問者。 –

+0

出於同樣的原因'field_name ='foo'; save'不會在字段中保存'foo' – apneadiving

回答

1

您的should_receive測試證明attach_roles正在被調用,它只是沒有達到您的預期。

我看到有兩件事讓我擔心。

@apneadiving指出的是同樣的事情。

當試圖在Ruby中分配實例變量時,您必須使用self.roles。我不確定<< x是如何工作的。如果它是類似於roles= roles + x的語法糖,那麼你需要self.roles,但如果它是roles.insert(x)那麼你不需要。如有疑問,self.roles將永遠符合您的期望。

另一件與我有關的事情是,您在未保留的模型上使用<<。該操作具有破壞性,並會嘗試持續使用Role。由於您大概在第一次創建模型時稱其爲函數,因此此代碼僅在未保持時纔會運行。雖然我認爲它主要起作用,但我不確定這是否是你想要的。我認爲你會用更好:

def attach_roles 
    roles.build(Role.default) 
end 

這假定Role.default是返回一個屬性哈希值。我可能是錯誤的,但你的意圖。

我希望有幫助。