Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to include a trait by default in a factory? #528

Closed
chintanparikh opened this issue May 22, 2013 · 3 comments
Closed

Is it possible to include a trait by default in a factory? #528

chintanparikh opened this issue May 22, 2013 · 3 comments

Comments

@chintanparikh
Copy link

Consider this factory:

# Read about factories at http://github.com/thoughtbot/factory_girl

FactoryGirl.define do
  factory :follow_up do
    first_name      { Faker::Name.first_name }
    last_name       { Faker::Name.last_name }
    phone           { Faker::PhoneNumber.cell_phone.gsub(/[^\d]/, '').gsub(/^1/, '2')[0..9] }
    email           { Faker::Internet.email }
    email_preferred true
    consent         false

    trait :by_referral do
      association :hospital
      association :referral
      source { FollowUp::REFERRAL}
    end

    trait :by_provider do
      association :provider
      source { FollowUp::PROVIDER }
    end
  end
end

I want to either default to include the by_referral trait, or the by_provider trait. It shouldn't be valid if neither trait is included. Is this possible, or is there a better way to do this?

@joshuaclayton
Copy link
Contributor

There's no direct way to shut off a factory or force a trait to be included, but what about something like this?

trait :follow_up_defaults do
  first_name {}
  last_name {}
  # ...
end

factory :follow_up_from_referral, class: FollowUp do
  follow_up_defaults
  hospital
  referral
  source { FollowUp::REFERRAL }
end

factory :follow_up_from_provider, class: FollowUp do
  follow_up_defaults
  provider
  source { FollowUp::PROVIDER }
end

The other way would be to include a trait in a factory by default:

factory :follow_up do
  first_name {}
  last_name {}
  # ...
  by_referral # <== defaults to by_referral

  trait :by_referral do
    # ...
  end

  trait :by_provider do
    # ...
  end

The potential issue here is that the association from the base trait will always be included, even if it technically shouldn't be. The first solution (while feeling a bit weird) ensures that a follow up always falls into one of the two categories.

Let me know if anything's not clear or if you come up with any more ideas for how to solve this!

@chintanparikh
Copy link
Author

Turns out I can chuck an if statement into a factory, so this works:

# Read about factories at http://github.com/thoughtbot/factory_girl

FactoryGirl.define do
  factory :follow_up do
    first_name      { Faker::Name.first_name }
    last_name       { Faker::Name.last_name }
    phone           { Faker::PhoneNumber.cell_phone.gsub(/[^\d]/, '').gsub(/^1/, '2')[0..9] }
    email           { Faker::Internet.email }
    email_preferred true
    consent         false

    if [1, 2].sample == 1
      by_referral
    else
      by_provider
    end

    trait :by_referral do
      association :hospital
      association :referral
      source { FollowUp::REFERRAL}
    end

    trait :by_provider do
      association :provider
      source { FollowUp::PROVIDER }
    end
  end
end

Thanks @joshuaclayton

@ChrisBAshton
Copy link

In case anybody else comes across the same issue as me - you cannot have a default trait which has the same name as an existing factory. See alphagov/content-publisher#1568 (comment) for full context.

Instead of

image

trait :image do
  # etc
end

...I had to rename to:

for_image

trait :for_image do
  # etc
end

...as I already had an :image factory elsewhere in the repository.

This nuance is captured in the getting started guide: "Note that defining traits as implicit attributes will not work if you have a factory or sequence with the same name as the trait" - but is easy to miss if you are skimming.

ChrisBAshton added a commit to alphagov/content-publisher that referenced this issue Jan 3, 2020
This factory is about to be used by a number of subsequent
commits. For ease of rebasing/editing, I've encapsulated it in
one commit.

For the record, I attempted to name the factories `:image` and
`:file_attachment`, but as these names clashed with existing
factory names, it was trying to set `image`/`file_attachment`
attributes instead. I've gone into more detail here:
thoughtbot/factory_bot#528 (comment)
ChrisBAshton added a commit to alphagov/content-publisher that referenced this issue Jan 7, 2020
This factory is about to be used by a number of subsequent
commits. For ease of rebasing/editing, I've encapsulated it in
one commit.

For the record, I attempted to name the factories `:image` and
`:file_attachment`, but as these names clashed with existing
factory names, it was trying to set `image`/`file_attachment`
attributes instead. I've gone into more detail here:
thoughtbot/factory_bot#528 (comment)
ChrisBAshton added a commit to alphagov/content-publisher that referenced this issue Jan 7, 2020
This factory is about to be used by a number of subsequent
commits. For ease of rebasing/editing, I've encapsulated it in
one commit.

For the record, I attempted to name the factories `:image` and
`:file_attachment`, but as these names clashed with existing
factory names, it was trying to set `image`/`file_attachment`
attributes instead. I've gone into more detail here:
thoughtbot/factory_bot#528 (comment)
ChrisBAshton added a commit to alphagov/content-publisher that referenced this issue Jan 9, 2020
This factory is about to be used by a number of subsequent
commits. For ease of rebasing/editing, I've encapsulated it in
one commit.

For the record, I attempted to name the factories `:image` and
`:file_attachment`, but as these names clashed with existing
factory names, it was trying to set `image`/`file_attachment`
attributes instead. I've gone into more detail here:
thoughtbot/factory_bot#528 (comment)
ChrisBAshton added a commit to alphagov/content-publisher that referenced this issue Jan 9, 2020
This factory is about to be used by a number of subsequent
commits. For ease of rebasing/editing, I've encapsulated it in
one commit.

For the record, I attempted to name the factories `:image` and
`:file_attachment`, but as these names clashed with existing
factory names, it was trying to set `image`/`file_attachment`
attributes instead. I've gone into more detail here:
thoughtbot/factory_bot#528 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants