Skip to content

Commit

Permalink
Support uuid primary keys in build_stubbed
Browse files Browse the repository at this point in the history
fixes #1498
closes #1514

Co-authored-by: Alexandre Ruban <alexandre@hey.com>
  • Loading branch information
2 people authored and mike-burns committed Oct 20, 2023
1 parent 8f4f899 commit bea80dc
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 22 deletions.
17 changes: 14 additions & 3 deletions lib/factory_bot/strategy/stub.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
76 changes: 57 additions & 19 deletions spec/acceptance/stub_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit bea80dc

Please sign in to comment.