没有 class_name 的 FactoryBot 命名空间模型

FactoryBot namespaced models without class_name

我有这样命名空间的模型:

class Vehicle < ActiveRecord::Base; end

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

在为这些模型创建工厂时,它们是按以下方式设置的:

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

这会产生以下弃用警告:

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.

是否有一种格式可以编写一个符号来命名这些工厂,这样我就不需要使用 class 名称来遵守弃用警告?

关于 :class 选项的行为方式或它期望的值,文档并不是很有用,但源代码更有用。从错误信息回溯我们发现 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

第一个分支中的key.to_sym是"I want a Symbol or String"的惯用语。第二个分支中的 key.to_s.underscore.to_sym 告诉我们期望的格式。

如果你 运行 Vehicle::Carto_s.underscore,你会得到 'vehicle/car' 所以这些应该有效:

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

或者如果你真的想要 Symbols(或者对标点符号感兴趣):

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

您也可以:

factory Vehicle::Car.to_s.underscore.to_sym, class: Vehicle::Car do; end

您可以只使用字符串形式的完全限定 class 名称:

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

如果您开始使用符号,:'Vehicle::Car'(如其他地方所建议的)或 'Vehicle::Car'.to_sym 应该可以工作,尽管我不确定这在测试上下文中有多大用处。