Home > other >  FactoryBot some columns are dependent rails
FactoryBot some columns are dependent rails

Time:06-21

I have a address model where I have validation if country, city, state and postal code has a valid combination.

address_factory

    city { Faker::Address.city }
    state { Faker::Address.state }
    postcode { Faker::Address.postcode }
    country { ISO3166::Country.countries.sample.alpha2 }

As each field id being populated randomly, validation get failed. I don't want to hard code these values. I have a comma separated file with valid combinations.

CodePudding user response:

this worked for me. api/spec/support/address_helper.rb

module AddressHelper
  module_function

  def csv_data
    file_path = Rails.root.join("spec", "fixtures", "australian_addresses.csv")
    csv_text = File.read(file_path)
    CSV.parse(csv_text, headers: true)
  end

  def random_location
    size = csv_data.length - 1
    index = Random.rand(0..size)
    csv_data[index].to_hash
  end
end

RSpec.configure do |config|
  config.include AddressHelper
end

spec/factories/address_factory.rb

factory :address do
    transient do
      location { AddressHelper.random_location }
    end
    name { Faker::Name.name }
    city { location["city"] }
    state { location["state"] }
    postcode { location.values.first }
    country { location["country"] }
    street_1 { Faker::Address.street_address }
    email { Faker::Internet.email }
end

CodePudding user response:

The factory is to create model instances for testing, and the field values should be valid by default when an instance is created. This is the reason we ask for validations, because the value validity depends on them.

Your current solution has a problem that the csv file is read each time when the instance is created, and it may slow down tests. It's not necessary to pick an valid value from the whole list unless you have a reason. (If you want to test validations, you should write test cases for them, not in the factory).

A more practical way is just preparing some valid values and random pick them in factory, for example: city: { ['city1', 'city2', 'city3'].sample }. It should be sufficient for most use cases.

  • Related