Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FactoryBot namespaced models without class_name

I have models which are namespaced such as this:

class Vehicle < ActiveRecord::Base; end

class Vehicle::Car < Vehicle; end
class Vehicle::Train < Vehicle; end
class Vehicle::Jet < Vehicle; end

When creating factories for these models, they were set up in the following way:

factory :vehicle_car, class: Vehicle::Car do; end
factory :vehicle_train, class: Vehicle::Train do; end
factory :vehicle_jet, class: Vehicle::Jet do; end

This produces the following deprecation warning:

DEPRECATION WARNING: Looking up factories by class is deprecated and will be removed in 5.0. Use symbols instead and set FactoryBot.allow_class_lookup = false.

Is there a format for writing a symbol to name these factories such that I do not need to use the class name to comply with the deprecation warning?

like image 883
Michael Fich Avatar asked May 20 '18 18:05

Michael Fich


2 Answers

The documentation wasn't terribly useful as to how the :class option behaves or what it expects as its value but the source was more helpful. Backtracking from the error message we find FactoryBot::Decorator::ClassKeyHash#symbolize_keys:

def symbolized_key(key)
  if key.respond_to?(:to_sym)
    key.to_sym
  elsif FactoryBot.allow_class_lookup
    ActiveSupport::Deprecation.warn "Looking up factories by class is deprecated and will be removed in 5.0. Use symbols instead and set FactoryBot.allow_class_lookup = false", caller
    key.to_s.underscore.to_sym
  end
end

The key.to_sym in the first branch is the usual idiom for "I want a Symbol or String". The key.to_s.underscore.to_sym in the second branch tells us what format is expected.

If you run Vehicle::Car through to_s.underscore, you get 'vehicle/car' so these should work:

factory :vehicle_car,   class: 'vehicle/car'   do; end
factory :vehicle_train, class: 'vehicle/train' do; end
factory :vehicle_jet,   class: 'vehicle/jet'   do; end

or if you really want Symbols (or have a thing for punctuation):

factory :vehicle_car,   class: :'vehicle/car'   do; end
factory :vehicle_train, class: :'vehicle/train' do; end
factory :vehicle_jet,   class: :'vehicle/jet'   do; end
like image 68
mu is too short Avatar answered Sep 21 '22 02:09

mu is too short


Also you can:

factory Vehicle::Car.to_s.underscore.to_sym, class: Vehicle::Car do; end
like image 41
korotindev Avatar answered Sep 21 '22 02:09

korotindev