shoulda匹配器应该validate_uniqueness_of与范围失败

我有3个型号,用户,游戏和播放器。 用户和游戏之间基本上存在多对多的关系,玩家作为联接表,除了玩家有其他信息,因此它有自己的模型。

玩家需要游戏ID和用户ID的唯一组合,所以我试着在玩家中说:

validates_uniqueness_of :user_id, :scope => :game_id 

然后在我的规范中,我说(使用shoulda matchers):

 it { should validate_uniqueness_of(:user_id).scoped_to(:game_id)} 

以下是玩家定义的关系:

 belongs_to :game, :inverse_of => :players belongs_to :user, :inverse_of => :players 

但我在该规范上得到一个ActiveRecord :: statementinvalid错误

 ActiveRecord::StatementInvalid: Mysql2::Error: Column 'game_id' cannot be null: INSERT INTO `players` ETC... 

知道出了什么问题吗?

这是一个众所周知的问题 。 如果作用域字段依赖于模型并且还设置为:null => false ,则会出现此错误。

另外,看看rails列不能为null:

虽然这是一个已知问题,但还是有办法解决它。

如果您首先创建一个记录,然后测试唯一性validation,它将起作用。

所以,而不是简单的写作

 it { should validate_uniqueness_of(:user_id) } 

你可以写

 it do FactoryGirl.create(:player) should validate_uniqueness_of(:user_id) end 

并且唯一性validation规范将起作用。

参考: http : //rubydoc.info/github/thoughtbot/shoulda-matchers/master/frames

您可以在此处阅读官方源代码中提到的问题和解决方案

一个解决方案是:

 describe Player do describe "validations" do it do expect(Player.new(game_id: 1)). to validate_uniqueness_of(:user_id). scoped_to(:game_id) end end end 

对于今天遇到此问题的人来说,这是一个更新的解决方案。

添加主题,以便测试具有值的记录。

另外,请注意较新的RSpec语法。

  subject { create(:player) } it { is_expected.to validate_uniqueness_of(:user_id).scoped_to(:game_id)} 

查看github上的文件以获取更多信息