Making factory_bot work with read-only models
In one of our apps we need to ensure that all models are in read-only mode. Still, for testing purposes we need to be able to create instances of such models. Following code makes it possible.
# spec/models/application_record_spec.rb
require 'rails_helper'
RSpec.describe ApplicationRecord do
it 'ensures all descendants are read-only' do
Unit = Class.new(ApplicationRecord)
expect(Unit.new.readonly?).to eq true
expect { Unit.create! }.to raise_exception(ActiveRecord::ReadOnlyRecord)
end
it 'allows creating objects using factories' do
Unit = Class.new(ApplicationRecord)
expect { read_only(:unit) }.to change { Unit.count }.by(1)
end
it 'disallows updating objects' do
Unit = Class.new(ApplicationRecord)
unit = read_only(:unit)
expect { unit.update_attributes!(name: 'New name') }.to \
raise_exception(ActiveRecord::ReadOnlyRecord)
end
end
# spec/support/factory_bot.rb
module FactoryBot
module Strategy
class ReadOnly < Create
def result(evaluation)
is_readonly = evaluation.object.readonly?
evaluation.object.define_singleton_method(:readonly?, -> { false })
super.tap do |object|
object.define_singleton_method(:readonly?, -> { is_readonly })
end
end
end
end
end
FactoryBot.register_strategy(:read_only, FactoryBot::Strategy::ReadOnly)
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
# spec/factories/units_factory.rb
FactoryBot.define do
factory :unit do
sequence(:name) { |i| "Unit #{i}" }
end
end
Tweet