2015-06-09 66 views
1

我在使用外鍵的燈具設置測試時遇到了問題!如果有人能幫助我理解這一點,我將非常感激。例如,:user_type模型引用了:role模型,當測試被執行時,並且測試數據庫中的所有數據被刪除以再次被重新插入時,Rails首先從角色模型中刪除數據而不是首先從:user_type刪除數據,然後從:role刪除數據。Ruby on Rails使用外鍵刪除燈具

的燈具:

#roles.yml 
technical: 
    name: 'Technical' 
    obs: 'User Role for technical/maintenance users!' 


#user_types.yml 
technic: 
    role: technical 
    name: 'Technic' 
    is_admin: true 

測試:

#app/test/models/role_test.rb 
require 'test_helper' 

class RoleTest < ActiveSupport::TestCase 
    fixtures :roles 

    test 'save Role without name' do 
    data = Role.new() 
    data.valid? 
    assert data.errors.added?(:name, :blank), 'Role saved without name!' 
    end 
end 


#app/test/models/user_type_test.rb 
require 'test_helper' 

class UserTypeTest < ActiveSupport::TestCase 
    fixtures :user_types 

    test 'save User Type without role_id' do 
    data = UserType.new(:name => 'public') 
    data.valid? 
    assert data.errors.added?(:role_id, :blank), 'User Type saved without role' 
    end 
end 

當測試運行的第一次,一切都OK。 Rails清理數據庫(在這一點上仍然是空的,所以沒有違反約束),然後插入燈具的數據,測試運行良好。 下次我嘗試運行測試時,它們會失敗,因爲當rails開始從數據庫中刪除數據時,它將以角色模型/表而不是user_type開始!由於在這些模型中定義的外鍵會發生違規,因爲user_type仍然引用模型表中的數據!

這應該如何正確完成? 有沒有任何機制可以告訴導軌銷燬燈具數據的命令?順便說一句,我使用RubyOnRails 4和Firebird 2.5。

我一直在爲此奮鬥了幾天,我一直沒有做到這一點!

預先感謝您!

+0

我還沒有嘗試過自己,但您可以查看http://api.rubyonrails.org/classes/ActiveRecord/TestFixtures.html並覆蓋ActiveSupport :: TestCase公共接口,如test/test_helper.rb中的setup/teardown。 。如果它不工作,不要downvote我:) – sethi

回答

12

我遇到過類似的問題,但是我用的是PostgreSQL。我發佈了我的解決方案,希望Firebird有一個類似的解決方案(我沒有親自使用過)。

正如你所提到的,當Rails執行測試套件時,它首先刪除數據庫表中的所有數據。這在外鍵約束條件下很棘手。理論上,處理這些限制的一種方法是找出刪除記錄的適當順序。

但是,至少對於PostgreSQL,Rails實際上是通過暫時禁用觸發器來避免這個問題,否則這些觸發器將會阻止違反這些外鍵約束。爲此,它會用下面的(可能是供應商特定的)對SQL命令,之前執行和刪除命令後:

ALTER TABLE tablename DISABLE TRIGGER ALL 
ALTER TABLE tablename ENABLE TRIGGER ALL 

這裏有一個問題:只有超級用戶角色(其中「角色」,基本意思是「用戶」在這種情況下)可以執行這些命令。實際上,Rails不能運行測試,除非它使用具有超級用戶特權的PostgreSQL角色。也許Firebird也有超級用戶?

旁註PostgreSQL的用戶這個問題:

授予超級用戶(僅做此對您的測試或開發數據庫)

運行該SQL語句:ALTER USER myuser WITH SUPERUSER;

這是嘗試而不超級用戶權限,以測試時出現像Rails 4.2.4的錯誤消息:

ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: update or delete on table "tablename" violates foreign key constraint

在Rails的未來版本中,將出現這個更具體的錯誤消息:

WARNING: Rails was not able to disable referential integrity. This is most likely caused due to missing permissions. Rails needs superuser privileges to disable referential integrity.

見導軌/導軌commit 72c1557PR #17726的更多細節。