Richlewis
Richlewis

Reputation: 15384

Write an Rspec test to test multiple nested_attibutes

I am trying to put together a test that will test an object with its nested_attributes.

I have a simple setup:

class Animal < ActiveRecord::Base
 has_many :animal_images
end

class AnimalImage < ActiveRecord::Base
 belongs_to :animal
end

From the factory_girl docs you can create an associated object like so:

FactoryGirl.define do
 factory :animal, class: Animal do

  ignore do
   images_count 1
  end

   after(:create) do |animal, evaluator|
    create_list(:animal_image, evaluator.images_count, animal: animal)
   end
 end 
end

FactoryGirl.define do
  factory :animal_image do

  image { File.open("#{Rails.root}/spec/fixtures/yp2.jpg") }
 end
end

So how would I construct a test to look at a custom validation method that validates the number of images?

Custom method:

def max_num_of_images
 if image.size >= 4
  errors.add(:base, "Only 3 images allowed")
 end
end

But where would I use this, in Animal or AnimalImage model? Am I to assume the AnimalImage model as I have access to the image attribute?

So far I have this:

it 'is invalid with 4 images' do
 animal = FactoryGirl.create(:animal, images_count: 4)
 animal_image = AnimalImage.create!(animal: animal, image: # how do I pass the 4 images I created earlier?)
 ap(animal)
 ap(animal_image)
end

So ap(animal) will return:

#<Animal:0x00000001c9bbd8> { :id => 52 }

and ap(animal_image) will return:

#<AnimalImage:0x00000005457b30> { :id => 231, :animal_id => 52 }

What I need to do is create 4 animal_images with the same animal_id and have my validation fail it as there are more than 3 images. How can I go about this?

Upvotes: 0

Views: 61

Answers (1)

nikolayp
nikolayp

Reputation: 17949

If i understood right, you can create array of images like:

FactoryGirl.define do
  factory :animal do
   name 'monkey'

    trait :with_image
      create_list(:animal_images, 3)
    end

    trait :with_5_images
      create_list(:animal_images, 5)
    end
  end 
end

FactoryGirl.define do
  factory :animal_image do
    image { File.open("#{Rails.root}/spec/fixtures/yp2.jpg") }
  end
end

describe Animal do
  subject(:animal) { build :animal, :with_images }
  let(:invalid_animal) { build :animal, :with_5_images }

  it { expect(subject.valid?).to be_truthy }
  it { expect(invalid_aminal.valid?).to be_falsy }
end

Upvotes: 0

Related Questions