联接表中的Factory Bot HABTM nil值

时间:2019-01-14 17:15:26

标签: ruby-on-rails factory-bot rspec-rails has-and-belongs-to-many ruby-on-rails-5.2

在为Rails应用程序运行rspec(带有Factory Bot)测试时,出现一个(令人沮丧的)错误。我看到以下错误:

V = np.random.rand(200)
models_by_name['dbow+dmc'].docvecs.most_similar([V])

AttributeError: 'ConcatenatedDocvecs' object has no attribute 'most_similar'

这是断断续续的-不同的测试会在不同的运行中引发错误-这可能表明存在竞争状况?

我的模型配置为:

ActiveRecord::NotNullViolation:
        Mysql2::Error: Field 'group_id' doesn't have a default value: INSERT INTO `groups_users` VALUES ()

工作人员必须属于一个组-验证如下:

User habtm Groups
Groups habtm Users

用户

validates :groups, presence: { message: 'Staff must be in at least one group' }, if: :staff?

factory :a_staff_member, class: User do
    first_name { Faker::Name.first_name }
    last_name { Faker::Name.last_name }
    username { "#{first_name}_#{last_name}".downcase.gsub(/[^a-z]/i, '') }
    email { "#{first_name}.#{last_name}@example.ac.uk".downcase }
    user_type { :staff }
    groups {|s| [s.association(:group)]}
end

所有失败测试中的共同因素是用户创建工厂(并且给定用户的组创建必须属于一个组)-所以这就是我一直在努力的地方。

鉴于错误是在groups_users表上,我猜测它是在组存在于groups表中之前试图将条目保存到联接表中?

基于其他SO帖子并浏览了Internet,我尝试了各种方法来设置组:

FactoryBot.define do
  factory :group do
    sequence(:title) { |n| "Group Number #{n}" }
    sequence(:short_title) { |n| "GRP#{n}" }
    sequence(:url_slug) { |n| "grp#{n}" }
  end
end

通过实例化用户

1) groups {|s| [s.association(:group)]}

2) after(:build) {|user| user.groups = [create(:group)]}

3) groups {[FactoryBot.create(:group)]}

在各个规格中-在那里没有令人兴奋的地方。

但是,无论如何我在工厂中创建组都没有任何区别-而且我的想法已经用完-任何指针或建议都将不胜感激!

3 个答案:

答案 0 :(得分:1)

我认为尝试通过串联更改相等性可能会起作用。

我要添加after(:create) { |user| user.groups << create(:group) }

移动到after(:create)是这里的主要任务,因为您面临的问题似乎还试图为尚未创建的记录添加联接表记录。

答案 1 :(得分:1)

设法找出问题所在。在工厂中创建该组并将其分配给用户的点上放置了一些全面的调试消息后,很明显,与这些联接表之间的nil值有关的错误消息实际上是红色鲱鱼,在工厂外造成的。

我认为该问题是由于在Capybara的两次测试之间未清理用户会话/登录引起的。

添加:

config.after :each do
  Warden.test_reset!
end
/spec/spec_helper.rb

似乎已解决了该问题。希望在这次调查中拔出的头发能重新长出来!

答案 2 :(得分:0)

我认为,如果您这样更改,它可能会起作用。

 from
 after(:build) {|user| user.groups = [create(:group)]}

 to
 after(:create) {|user| user.groups = [create(:group)]}

一旦通过运行“ create”创建了一个用户ID,那么“ users.groups”将是可以接受的。