user
user

Reputation: 1381

Rails factory_girls and validation issue

I have HABTM association

my models

 class Ssr < ActiveRecord::Base
    has_and_belongs_to_many :ssr_groups
    validates :ssr_groups, presence: true
 end

class SsrGroup < ActiveRecord::Base
  has_and_belongs_to_many :ssrs, dependent: :destroy
  validates :name, presence: true
end

my factories

  FactoryGirl.define do
  factory :ssr do
    type 'type' 
    ssr_groups
   end
 end

FactoryGirl.define do
  factory :ssr_group, class: 'SsrGroup', aliases: [:ssr_groups] do
    name { SecureRandom.hex }
  end
end

My problem is when i want to create FactoryGirl.create(:ssr)

i have got NoMethodError: undefined method each for #<SsrGroup:0x007fbfdf792100>

Why it happens?

Upvotes: 1

Views: 106

Answers (1)

ascherman
ascherman

Reputation: 1832

Thee problem is that your ssr factory is expecting a collection of ssr_group, and what you are doing is getting just one. That's why the error, because it's trying to do foreach on the created ssr_group.

To fix this, you can do something like this:

FactoryGirl.define do
  factory :ssr do
    type 'type' 
    after(:create) do |ssr, evaluator|
      create_list(:ssr_group, 1, ssrs: [ssr])
    end
  end
end

You can use the build strategy instead of the create if preferred.

EDIT:

You can improve your factory a little, like this:

FactoryGirl.define do
  factory :ssr do
    type 'type' 

    factory :ssr_with_groups do
      transient do
        groups_count 5 # Default count of ssr_groups it will create
      end

      after(:create) do |ssr, evaluator|
        create_list(:ssr_group, evaluator.groups_count, ssrs: [ssr])
      end
    end
  end
end

That way, it's more flexible and you can use it like this:

create(:ssr_with_groups, groups_count: 10)

And it would create a ssr with 10 ssr_groups.

EDIT 2:

Given you have a presence validation on the association, you need to add the associations before saving the object, so use the build strategy instead, like this:

FactoryGirl.define do
  factory :ssr do
    type 'type' 
    after(:build) do |ssr, evaluator|
      ssr.ssr_groups << build_list(:ssr_group, 1, ssrs: [ssr])
    end
  end
end

You can take a deeper look at the docs: http://www.rubydoc.info/gems/factory_girl/file/GETTING_STARTED.md#Associations

Upvotes: 1

Related Questions