diff --git a/lib/factory_bot/strategy/stub.rb b/lib/factory_bot/strategy/stub.rb index ccec477e..696f65ee 100644 --- a/lib/factory_bot/strategy/stub.rb +++ b/lib/factory_bot/strategy/stub.rb @@ -47,13 +47,17 @@ def to_sym private - def next_id - @@next_id += 1 + def next_id(result_instance) + if uuid_primary_key?(result_instance) + SecureRandom.uuid + else + @@next_id += 1 + end end def stub_database_interaction_on_result(result_instance) if has_settable_id?(result_instance) - result_instance.id ||= next_id + result_instance.id ||= next_id(result_instance) end result_instance.instance_eval do @@ -83,6 +87,13 @@ def has_settable_id?(result_instance) result_instance.class.primary_key end + def uuid_primary_key?(result_instance) + result_instance.respond_to?(:column_for_attribute) && + (column = result_instance.column_for_attribute(result_instance.class.primary_key)) && + column.respond_to?(:sql_type) && + column.sql_type == "uuid" + end + def clear_changes_information(result_instance) if result_instance.respond_to?(:clear_changes_information) result_instance.clear_changes_information diff --git a/spec/acceptance/stub_spec.rb b/spec/acceptance/stub_spec.rb index 00658601..3a4847a1 100644 --- a/spec/acceptance/stub_spec.rb +++ b/spec/acceptance/stub_spec.rb @@ -59,43 +59,81 @@ end end -describe "a stubbed instance with no primary key" do - it "builds a stubbed instance" do - using_model_without_pk do - FactoryBot.define do - factory :model_without_pk +describe "overridden primary keys conventions" do + describe "a stubbed instance with a uuid primary key" do + it "builds a stubbed instance" do + using_model("ModelWithUuid", primary_key: :uuid) do + FactoryBot.define do + factory :model_with_uuid + end + + model = FactoryBot.build_stubbed(:model_with_uuid) + expect(model).to be_truthy end + end + + it "behaves like a persisted record" do + using_model("ModelWithUuid", primary_key: :uuid) do + FactoryBot.define do + factory :model_with_uuid + end - model = FactoryBot.build_stubbed(:model_without_pk) - expect(model).to be_truthy + model = FactoryBot.build_stubbed(:model_with_uuid) + expect(model).to be_persisted + expect(model).not_to be_new_record + end + end + + it "has a uuid primary key" do + using_model("ModelWithUuid", primary_key: :uuid) do + FactoryBot.define do + factory :model_with_uuid + end + + model = FactoryBot.build_stubbed(:model_with_uuid) + expect(model.id).to be_a(String) + end end end - it "behaves like a persisted record" do - using_model_without_pk do - FactoryBot.define do - factory :model_without_pk + describe "a stubbed instance with no primary key" do + it "builds a stubbed instance" do + using_model("ModelWithoutPk", primary_key: false) do + FactoryBot.define do + factory :model_without_pk + end + + model = FactoryBot.build_stubbed(:model_without_pk) + expect(model).to be_truthy end + end - model = FactoryBot.build_stubbed(:model_without_pk) - expect(model).to be_persisted - expect(model).not_to be_new_record + it "behaves like a persisted record" do + using_model("ModelWithoutPk", primary_key: false) do + FactoryBot.define do + factory :model_without_pk + end + + model = FactoryBot.build_stubbed(:model_without_pk) + expect(model).to be_persisted + expect(model).not_to be_new_record + end end end - def using_model_without_pk - define_class("ModelWithoutPk", ActiveRecord::Base) + def using_model(name, primary_key:) + define_class(name, ActiveRecord::Base) connection = ActiveRecord::Base.connection begin - clear_generated_table("model_without_pks") - connection.create_table("model_without_pks", id: false) do |t| + clear_generated_table(name.tableize) + connection.create_table(name.tableize, id: primary_key) do |t| t.column :updated_at, :datetime end yield ensure - clear_generated_table("model_without_pks") + clear_generated_table(name.tableize) end end end