### Install Dependencies Source: https://github.com/thoughtbot/factory_bot/blob/main/CONTRIBUTING.md Run this command to install all necessary project dependencies. ```sh bundle install ``` -------------------------------- ### Full URI Example with Nested Sequences Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/sequences/sequence-uris.md This example demonstrates defining and referencing sequences at global, trait, factory, and nested trait levels. Comments indicate the correct URI for each sequence. ```ruby FactoryBot.define do sequence(:sequence) {|n| "global_sequence_#{n}"} # generate(:sequence) trait :global_trait do sequence(:sequence) {|n| "global_trait_sequence_#{n}"} # generate(:global_trait, :sequence) end factory :user do sequence(:sequence) {|n| "user_sequence_#{n}"} # generate(:user, :sequence) trait :user_trait do sequence(:sequence) {|n| "user_trait_sequence_#{n}"} # generate(:user, :user_trait, :sequence) end factory :author do sequence(:sequence) {|n| "author_sequence_#{n}"} # generate(:author, :sequence) trait :author_trait do sequence(:sequence) {|n| "author_trait_sequence_#{n}"} # generate(:author, :author_trait, :sequence) end end end end ``` -------------------------------- ### Define a User Factory Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/modifying-factories/summary.md This is an example of a basic factory definition for a User. ```ruby FactoryBot.define do factory :user do full_name { "John Doe" } sequence(:username) { |n| "user#{n}" } password { "password" } end end ``` -------------------------------- ### Create a User Instance Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Create an instance of the :user factory, which includes a confirmation callback. This is a basic usage example after defining the factory. ```ruby create(:user) ``` -------------------------------- ### Install factory_bot Gem Manually Source: https://github.com/thoughtbot/factory_bot/blob/main/README.md If you prefer to install the gem directly from your shell without using a Gemfile, use this command. ```shell gem install factory_bot ``` -------------------------------- ### Multi URIs with Aliases Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/sequences/sequence-uris.md Demonstrates how sequences can have multiple URIs when factories or traits have aliases. The example shows four ways to reference the same sequence. ```ruby factory :user, aliases: [:author] do trait :user_trait, aliases: [:author_trait] do sequence(:sequence) {|n| "author_trait_sequence_#{n}"} end end # generate(:user, :user_trait, :sequence) # generate(:user, :author_trait, :sequence) # generate(:author, :user_trait, :sequence) # generate(:author, :author_trait, :sequence) ``` -------------------------------- ### Simple Factory Callback Order Example Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/callbacks/callback_order.md Demonstrates the callback execution order for a simple factory with global, factory, and trait callbacks. Observe the sequence of 'before' and 'after' callbacks. ```ruby FactoryBot.define do before(:all) { puts "Global before(:all)" } after(:all) { puts "Global after(:all)" } factory :user do before(:all) { puts "User before(:all)" } after(:all) { puts "User after(:all)" } before(:build) { puts "User before(:build)" } after(:build) { puts "User after(:build)" } trait :trait_a do before(:build) { puts "Trait-A before(:build)" } after(:build) { puts "Trait-A after(:build)" } end trait :trait_b do before(:build) { puts "Trait-B before(:build)" } after(:build) { puts "Trait-B after(:build)" } end end end build(:user, :trait_b, :trait_a) # Result: # # 1. "Global before(:all)" # 2. "User before(:all)" # 3. "User before(:build) # 4. "Trait-B before(:build)" # 5. "Trait-A before(:build)" # 6. "User after(:build)" # 7. "Trait-B after(:build)" # 8. "Trait-A after(:build)" # 9. "Global after(:all)" # 10. "User after(:all)" ``` -------------------------------- ### Example Rake Task for Linting Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md An example Rake task demonstrating how to integrate FactoryBot.lint into your build process. Recommended for running before the test suite to catch factory errors. ```ruby task lint: :environment do FactoryBot.lint end ``` -------------------------------- ### Use FactoryBot Methods in Minitest Tests Source: https://github.com/thoughtbot/factory_bot/wiki/Integration:-Minitest After including the syntax methods, you can use `create`, `build`, `create_list`, and `build_list` directly within your test methods. This example shows creating a user with associated articles and building another entity. ```ruby def test_renders_itself user = create(:user, articles: build_list(:article, 2)) # not FactoryBot.create or FactoryBot.build_list writer = build(:writer) # not FactoryBot.build user.render(writer) assert_equal writer.to_s, "User with two articles" end ``` -------------------------------- ### Create Multiple User Instances with Traits Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/traits/using.md Apply traits to multiple instances created with `create_list`. This example creates three users, all with the `:admin` and `:active` traits, and a shared `name`. ```ruby factory :user do name { "Friendly User" } trait :active do name { "John Doe" } status { :active } end trait :admin do admin { true } end end # creates 3 admin users with :active status and name "Jon Snow" create_list(:user, 3, :admin, :active, name: "Jon Snow") ``` -------------------------------- ### Create User Instance with Traits Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/traits/using.md Use traits to apply specific attribute sets when creating a single instance. This example shows how to combine `:admin` and `:active` traits with an explicit `name` override. ```ruby factory :user do name { "Friendly User" } trait :active do name { "John Doe" } status { :active } end trait :admin do admin { true } end end # creates an admin user with :active status and name "Jon Snow" create(:user, :admin, :active, name: "Jon Snow") ``` -------------------------------- ### Use a Class Method for Initialization Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/custom-construction/summary.md Instantiate objects using a class method other than `new` by specifying it within `initialize_with`. This example uses `User.build_with_name`. ```ruby factory :user do name { "John Doe" } initialize_with { User.build_with_name(name) } end ``` -------------------------------- ### Install and Configure factory_bot Source: https://context7.com/thoughtbot/factory_bot/llms.txt Add factory_bot to your Gemfile and configure it for your test framework (RSpec, Minitest, Cucumber). For Rails projects, use factory_bot_rails. ```ruby gem "factory_bot", group: :test ``` ```ruby # RSpec configuration (spec/support/factory_bot.rb) RSpec.configure do |config| config.include FactoryBot::Syntax::Methods # Only needed when NOT using factory_bot_rails (auto-loads factories) config.before(:suite) do FactoryBot.find_definitions end end ``` ```ruby # Minitest / Test::Unit class ActiveSupport::TestCase include FactoryBot::Syntax::Methods end ``` ```ruby # Cucumber World(FactoryBot::Syntax::Methods) ``` -------------------------------- ### Define Custom Initialization for a User Factory Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/custom-construction/summary.md Override the default `new` behavior to pass arguments to the `initialize` method. This example demonstrates constructing a `User` object with a `name` argument. ```ruby class User attr_accessor :name, :email def initialize(name) @name = name end end sequence(:email) { |n| "person#{n}@example.com" } factory :user do name { "Jane Doe" } email initialize_with { new(name) } end build(:user).name # Jane Doe ``` -------------------------------- ### Association Overrides Example Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Demonstrates how attribute overrides can be used to link associated objects. ```ruby FactoryBot.define do factory :author do name { 'Taylor' } end factory :post do author end end eunji = build(:author, name: 'Eunji') post = build(:post, author: eunji) ``` -------------------------------- ### Define Custom Callbacks for a Strategy Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Define custom callbacks for a strategy to hook into the build process. This example adds callbacks for JSON generation. ```ruby class JsonStrategy def initialize @strategy = FactoryBot.strategy_by_name(:create).new end delegate :association, to: :@strategy def result(evaluation) result = @strategy.result(evaluation) evaluation.notify(:before_json, result) result.to_json.tap do |json| evaluation.notify(:after_json, json) evaluation.notify(:make_json_awesome, json) end end def to_sym :json end end FactoryBot.register_strategy(:json, JsonStrategy) FactoryBot.define do factory :user do before(:json) { |user| do_something_to(user) } after(:json) { |user_json| do_something_to(user_json) } callback(:make_json_awesome) { |user_json| do_something_to(user_json) } end end ``` -------------------------------- ### Add factory_bot to Gemfile Source: https://github.com/thoughtbot/factory_bot/blob/main/README.md Use this command to add factory_bot to your project's Gemfile. Ensure you run 'bundle install' afterwards. ```ruby bundle add factory_bot ``` -------------------------------- ### Implicit Factory Definition using method_missing Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/ref/method_missing.md This example demonstrates the implicit definition style using `method_missing`. It achieves the same results as the explicit definition but with less code by leveraging FactoryBot's intelligent method interpretation. ```ruby FactoryBot.define do sequence(:email) { |n| "person#{n}@example.com" } factory :account factory :organization factory :user do name { "Lord Nikon" } # no more `add_attribute` admin # no more :traits email # no more `add_attribute` account # no more `association` org factory: :organization # no more `association` trait :admin do admin { true } end end end ``` -------------------------------- ### Inherited Factory Callback Order Example Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/callbacks/callback_order.md Illustrates the callback execution order in an inheritance chain, including global, parent, child, and multiple trait callbacks. Pay attention to how callbacks are layered. ```ruby FactoryBot.define do before(:all) { puts "Global before(:all)" } before(:build) { puts "Global before(:build)" } after(:build) { puts "Global after(:build)" } after(:all) { puts "Global after(:all)" } factory :parent do before(:all) { puts "Parent before(:all)" } before(:build) { puts "Parent before(:build)" } after(:all) { puts "Parent after(:all)" } after(:build) { puts "Parent after(:build)" } trait :trait_a do before(:build) { puts "Trait-A before(:build)" } after(:build) { puts "Trait-A after(:build)" } end factory :child do before(:all) { puts "Child before(:all)" } before(:build) { puts "Child before(:build)" } after(:build) { puts "Child after(:build)" } after(:all) { puts "Child after(:all)" } trait :trait_b do before(:build) { puts "Trait-B before(:build)" } after(:build) { puts "Trait-B after(:build)" } after(:all) { puts "Trait-B after(:all)" } end trait :trait_c do before(:build) { puts "Trait-C before(:build)" } after(:build) { puts "Trait-C after(:build)" } before(:all) { puts "Trait-C before(:all)" } end end end end build(:child, :trait_c, :trait_a, :trait_b) # Result: # # 1. "Global before(:all)" # 2. "Parent before(:all)" # 3. "Child before(:all)" # 4. "Trait-C before(:all)" # 5. "Global before(:build)" # 6. "Parent before(:build)" # 7. "Child before(:build)" # 8. "Trait-C before(:build)" # 9. "Trait-A before(:build)" # 10. "Trait-B before(:build)" # 11. "Global after(:build)" # 12. "Parent after(:build)" # 13. "Child after(:build)" # 14. "Trait-C after(:build)" # 15. "Trait-A after(:build)" # 16. "Trait-B after(:build)" # 17. "Global after(:all)" # 18. "Parent after(:all)" # 19. "Child after(:all)" # 20. "Trait-B after(:all)" ``` -------------------------------- ### Explicit Factory Definition with method_missing Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/ref/method_missing.md This example shows an explicit factory definition using `add_attribute`, `association`, and `traits`. It serves as a baseline for understanding the implicit syntax. ```ruby FactoryBot.define do sequence(:email) { |n| "person#{n}@example.com" } factory :account factory :organization factory :user, traits: [:admin] do add_attribute(:name) { "Lord Nikon" } add_attribute(:email) { generate(:email) } association :account association :org, factory: :organization trait :admin do add_attribute(:admin) { true } end end end ``` -------------------------------- ### Define a Custom JSON Strategy Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/custom-strategies/summary.md Implement a custom strategy by inheriting from an existing strategy or defining the required methods. This example creates a JSON strategy that uses the 'create' strategy internally and serializes the result to JSON. ```ruby class JsonStrategy def initialize @strategy = FactoryBot.strategy_by_name(:create).new end delegate :association, to: :@strategy def result(evaluation) @strategy.result(evaluation).to_json end def to_sym :json end end ``` -------------------------------- ### Define a Factory with Name and Attributes Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/defining/name-attributes.md This example shows how to define a factory named ':user'. FactoryBot will automatically guess the associated class as 'User'. Attributes like 'first_name', 'last_name', and 'admin' are set with default values. ```ruby FactoryBot.define do factory :user do first_name { "John" } last_name { "Doe" } admin { false } end end ``` -------------------------------- ### Use Custom Callbacks in Factory Definition Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/custom-callbacks/summary.md Register a custom strategy and then use its defined callbacks within a Factory Bot factory. This example uses `before`, `after`, and a custom named callback `make_json_awesome`. ```ruby FactoryBot.define do factory :user do before(:json) { |user| do_something_to(user) } after(:json) { |user_json| do_something_to(user_json) } callback(:make_json_awesome) { |user_json| do_something_to(user_json) } end end ``` -------------------------------- ### Create FactoryBot Objects in Spinach Steps Source: https://github.com/thoughtbot/factory_bot/wiki/Integration:-Spinach Use FactoryBot's `create` and `build_list` methods directly within a Spinach step to generate associated test data. This example creates a user with two associated articles. ```ruby step "a user with 2 articles" do @user = create(:user, articles: build_list(:article, 2)) end ``` -------------------------------- ### Register a Custom Build Strategy in factory_bot Source: https://context7.com/thoughtbot/factory_bot/llms.txt Implement `association`, `result`, and `to_sym` methods to define a custom strategy. Use `FactoryBot.register_strategy` to make it available. This example shows a 'json' strategy that converts the built object to JSON. ```ruby class JsonStrategy def initialize @strategy = FactoryBot.strategy_by_name(:create).new end delegate :association, to: :@strategy def result(evaluation) evaluation.notify(:before_json, evaluation.object) json = @strategy.result(evaluation).to_json evaluation.notify(:after_json, json) json end def to_sym :json end end FactoryBot.register_strategy(:json, JsonStrategy) # Use the custom strategy FactoryBot.define do factory :user do name { "Jane Doe" } before(:json) { |u| u.name = u.name.downcase } after(:json) { |j| puts "Produced JSON: #{j}" } end end FactoryBot.json(:user) # => '{"name":"jane doe"}' ``` -------------------------------- ### Auto-Load Factories with factory_bot.find_definitions Source: https://context7.com/thoughtbot/factory_bot/llms.txt Scans the file system for factory definition files and loads them automatically. Called once during test suite setup when not using factory_bot_rails. Custom search paths can be specified. ```ruby # Default search paths: # factories.rb, factories/**/*.rb # test/factories.rb, test/factories/**/*.rb # spec/factories.rb, spec/factories/**/*.rb FactoryBot.find_definitions ``` ```ruby # Custom search paths FactoryBot.definition_file_paths = %w[custom/factories shared/factories] FactoryBot.find_definitions ``` -------------------------------- ### Define Custom Strategy with Callbacks Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/custom-callbacks/summary.md Define a custom strategy class that integrates with Factory Bot's callback system. This example shows a `JsonStrategy` that notifies callbacks before and after generating JSON. ```ruby class JsonStrategy def initialize @strategy = FactoryBot.strategy_by_name(:create).new end delegate :association, to: :@strategy def result(evaluation) result = @strategy.result(evaluation) evaluation.notify(:before_json, result) result.to_json.tap do |json| evaluation.notify(:after_json, json) evaluation.notify(:make_json_awesome, json) end end def to_sym :json end end FactoryBot.register_strategy(:json, JsonStrategy) ``` -------------------------------- ### Define Global Callbacks in FactoryBot Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/callbacks/global-callbacks.md Override callbacks for all factories by defining them within the `FactoryBot.define` block. This example shows how to add a `puts` statement after building and create an `AuditLog` after creating an object. ```ruby FactoryBot.define do after(:build) { |object| puts "Built #{object}" } after(:create) { |object| AuditLog.create(attrs: object.attributes) } factory :user do name { "John Doe" } end end ``` -------------------------------- ### Build Strategy: Get Attributes Hash Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Use the `attributes_for` strategy to get a hash of attributes suitable for building an object, without instantiating it. ```ruby # Returns a hash of attributes that can be used to build a User instance attrs = attributes_for(:user) ``` -------------------------------- ### Create a Post Instance Source: https://github.com/thoughtbot/factory_bot/wiki/How-factory_bot-interacts-with-ActiveRecord Calling `create(:post)` generates a `Post` instance with an associated `User`. ```ruby post = create(:post) ``` -------------------------------- ### Define Active Record Enum Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/traits/enum.md This is an example of an Active Record model with an enum attribute. ```ruby class Task < ActiveRecord::Base enum status: {queued: 0, started: 1, finished: 2} end ``` -------------------------------- ### Create User with Posts Helper Method Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md A helper method to create a user and associate a specified number of posts. Useful for testing has_many relationships. ```ruby def user_with_posts(posts_count: 5) FactoryBot.create(:user) do |user| FactoryBot.create_list(:post, posts_count, user: user) end end create(:user).posts.length # 0 user_with_posts.posts.length # 5 user_with_posts(posts_count: 15).posts.length # 15 ``` -------------------------------- ### Default Sequence Increment Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/sequences/without-a-block.md When a sequence is defined without a block, its value will increment automatically, starting from its initial value. ```ruby factory :post do sequence(:position) end ``` -------------------------------- ### Build Strategy: Create a Saved Object Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Use the `create` strategy to instantiate and save an object to the database. ```ruby # Returns a saved User instance user = create(:user) ``` -------------------------------- ### Use FactoryBot Methods in Tests Source: https://github.com/thoughtbot/factory_bot/wiki/Integration:-Test::Unit Demonstrates using `create`, `build_list`, and `build` directly within a Test::Unit test method after including `FactoryBot::Syntax::Methods`. ```ruby def test_renders_itself user = create(:user, articles: build_list(:article, 2)) # not FactoryBot.create or FactoryBot.build_list writer = build(:writer) # not FactoryBot.build user.render(writer) assert writer.to_s == "User with two articles" end ``` -------------------------------- ### Rewind All Sequences Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/sequences/rewinding.md Use `FactoryBot.rewind_sequences` to reset all global and factory-defined sequences to their starting values. This affects all sequences defined within your application. ```ruby FactoryBot.define do sequence(:email) {|n| "person#{n}@example.com" } factory :user do sequence(:email) {|n| "user#{n}@example.com" } end end generate(:email) # "person1@example.com" generate(:email) # "person2@example.com" generate(:email) # "person3@example.com" generate(:user, :email) # "user1@example.com" generate(:user, :email) # "user2@example.com" generate(:user, :email) # "user3@example.com" FactoryBot.rewind_sequences generate(:email) # "person1@example.com" generate(:user, :email) # "user1@example.com" ``` -------------------------------- ### Override Sequence Initial Value Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/sequences/initial-value.md Set a specific starting number for a sequence. Any object responding to `#next` can be used as an initial value. ```ruby factory :user do sequence(:email, 1000) { |n| "person#{n}@example.com" } end ``` -------------------------------- ### Factory Bot Build Strategies Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/using-factories/build-strategies.md Demonstrates the usage of `build`, `create`, `attributes_for`, and `build_stubbed` strategies in Factory Bot. Use `build` for unsaved instances, `create` for saved instances, `attributes_for` for attribute hashes, and `build_stubbed` for stubbed objects. ```ruby user = build(:user) ``` ```ruby user = create(:user) ``` ```ruby attrs = attributes_for(:user) ``` ```ruby attributes_for(:user) => {email:, name:, **attrs} ``` ```ruby stub = build_stubbed(:user) ``` ```ruby create(:user) do |user| user.posts.create(attributes_for(:post)) end ``` -------------------------------- ### Format Code with Standard Source: https://github.com/thoughtbot/factory_bot/blob/main/CONTRIBUTING.md Run this command to automatically format your code using the Standard linter. ```sh bundle exec rake standard:fix ``` -------------------------------- ### Create Profile with Languages (Callback) Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/cookbook/has_and_belongs_to_many-associations.md This approach uses a Factory Bot callback to create associated languages after the profile is created. It leverages transient attributes for flexibility in specifying the number of languages. ```ruby factory :profile_with_languages do transient do languages_count { 2 } end after(:create) do |profile, context| create_list(:language, context.languages_count, profiles: [profile]) profile.reload end end ``` -------------------------------- ### Lint Specific Factories Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/linting-factories/summary.md Selectively lint factories by providing a collection of factories to the `lint` method. This example rejects factories prefixed with 'old_'. ```ruby factories_to_lint = FactoryBot.factories.reject do |factory| factory.name =~ /^old_/ end FactoryBot.lint factories_to_lint ``` -------------------------------- ### Using `after` and `callback` for after_create hook Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/ref/hooks.md Demonstrates the syntactic sugar of `after(:create)` compared to the more verbose `callback(:after_create)`. Both achieve the same result of executing code after an object is created. ```ruby after(:create) do |user, context| user.post_first_article(context.article) end ``` ```ruby callback(:after_create) do |user, context| user.post_first_article(context.article) end ``` -------------------------------- ### Inline Association with Factory Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/associations/specifying-the-factory.md Define an association inline using a block that calls `association` with the desired factory. This is useful for more complex association setups. ```ruby factory :post do # ... author { association :user } end ``` -------------------------------- ### Build and Publish Gem Source: https://github.com/thoughtbot/factory_bot/blob/main/RELEASING.md Build the gem package and push it to rubygems.org. Replace VERSION with the actual version number. ```bash gem build factory_bot.gemspec gem push factory_bot-VERSION.gem ``` -------------------------------- ### Use Alias for Commenter Association Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/aliases/summary.md Use the 'commenter' alias to associate a 'comment' with a 'user' factory. This simplifies the association definition, similar to the 'post' example. ```ruby factory :comment do # The alias allows us to write commenter instead of # association :commenter, factory: :user commenter body { "Great article!" } end ``` -------------------------------- ### Create Profile with Languages (Direct) Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/cookbook/has_and_belongs_to_many-associations.md Use this method to directly create a profile and associate a specified number of languages with it. The languages are created with the profile already associated. ```ruby def profile_with_languages(languages_count: 2) FactoryBot.create(:profile) do |profile| FactoryBot.create_list(:language, languages_count, profiles: [profile]) end end ``` -------------------------------- ### Default Association Strategy Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/associations/build-strategies.md Associations default to using the same build strategy as their parent object. This example shows how `build` and `create` affect associated objects. ```ruby FactoryBot.define do factory :author factory :post do author end end post = build(:post) post.new_record? # => true post.author.new_record? # => true post = create(:post) post.new_record? # => false post.author.new_record? # => false ``` -------------------------------- ### Run FactoryBot Lint Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/linting-factories/summary.md Call `FactoryBot.lint` to create each factory and catch any exceptions during the creation process. This helps identify invalid factories early. ```ruby FactoryBot.lint ``` -------------------------------- ### Define and Use Sequences Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/sequences/setting-the-value.md Define global and factory-specific sequences, including those within traits. Demonstrates initial generation and setting new values. ```ruby FactoryBot.define do sequence(:char, 'a') {|c| "global_character_#{c}" } factory :user do sequence(:name, %w[Jane Joe Josh Jayde John].to_enum) trait :with_email do sequence(:email) {|n| "user_#{n}@example.com" } end end end ``` ```ruby ## # char generate(:char) # "global_character_a" FactoryBot.set_sequence(:char, 'z') generate(:char) # "global_character_z" ``` ```ruby ## # user name generate(:user, :name) # "Jane" FactoryBot.set_sequence(:user, :name, 'Jayde') generate(:user, :name) # "Jayde" ``` ```ruby ## # user email generate(:user, :with_email, :email) # "user_1@example.com" FactoryBot.set_sequence(:user, :with_email, :email, 1_234_567) generate(:user, :with_email, :email) # "user_1234567@example.com" ``` -------------------------------- ### FactoryBot Lint Rake Task Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/linting-factories/summary.md Integrate `FactoryBot.lint` into a Rake task for execution before your test suite. This example uses a transaction and rollback to keep the database clean. ```ruby namespace :factory_bot do desc "Verify that all FactoryBot factories are valid" task lint: :environment do if Rails.env.test? conn = ActiveRecord::Base.connection conn.transaction do FactoryBot.lint raise ActiveRecord::Rollback end else system("bundle exec rake factory_bot:lint RAILS_ENV='test'") fail if $?.exitstatus.nonzero? end end end ``` -------------------------------- ### Build or Create Multiple Records Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/building-or-creating-multiple-records/summary.md Use `build_list` to create multiple instances without saving them to the database, and `create_list` to create multiple instances that are saved. ```ruby built_users = build_list(:user, 25) created_users = create_list(:user, 25) ``` -------------------------------- ### Define Sequence with Aliases and Default Counter Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/sequences/aliases.md Define a sequence with aliases, using the default starting value of 1 for its counter. The counter is shared among all aliases. ```ruby factory :user do sequence(:email, aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" } end ``` -------------------------------- ### Define Sequence with Aliases and Initial Value Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/sequences/aliases.md Define a sequence with an explicit starting value for its counter and assign multiple aliases. The counter is shared among all aliases. ```ruby factory :user do sequence(:email, 1000, aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" } end # will increase value counter for :email which is shared by :sender and :receiver generate(:sender) ``` -------------------------------- ### Default Initialize With - FactoryBot Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/ref/build-and-create.md The default `initialize_with` method uses `new` to create an instance of the factory's class. It provides access to the `attributes` hash for initializing the object. ```ruby initialize_with { new } ``` -------------------------------- ### Use Transient Attributes in FactoryBot Traits Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Traits can accept transient attributes, which are not persisted but can be used within callbacks. This example uses `amount` to create a `line_item` with a specific quantity. ```ruby factory :invoice do trait :with_amount do transient do amount { 1 } end after(:create) do |invoice, evaluator| create :line_item, invoice: invoice, amount: evaluator.amount end end end create :invoice, :with_amount, amount: 2 ``` -------------------------------- ### Create a Child Factory Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/modifying-factories/summary.md This demonstrates creating a child factory that inherits from and adds attributes to a parent factory. ```ruby FactoryBot.define do factory :application_user, parent: :user do full_name { "Jane Doe" } date_of_birth { 21.years.ago } health { 90 } end end ``` -------------------------------- ### Define a User Factory with a Callback Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Define a factory for a User model and include a callback to confirm the user after creation. Use this when you need to perform actions post-creation. ```ruby FactoryBot.define do factory :user do after :create, &:confirm! end end ``` -------------------------------- ### Use Symbol#to_proc for Callbacks Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Callbacks can utilize `Symbol#to_proc` for concise definition when the callback action is a single method call on the object. This example uses `confirm!` on a `User` object. ```ruby # app/models/user.rb class User < ActiveRecord::Base def confirm! # confirm the user account end end # In your factory definition: # factory :user do # confirm! # end ``` -------------------------------- ### Create Persisted Instance with create Source: https://context7.com/thoughtbot/factory_bot/llms.txt Builds and saves an instance by calling `save!` on it. Triggers `after(:build)`, `before(:create)`, and `after(:create)` callbacks. Attributes can be overridden, and a block can be used for setting up associations after creation. ```ruby # Returns a saved User instance user = create(:user) user.persisted? # => true ``` ```ruby # Override attributes; still persists the record user = create(:user, first_name: "Bob", admin: false) ``` ```ruby # Block form — useful for setting up associations after creation user = create(:user) do |u| u.posts.create(title: "Hello World", body: "My first post") end ``` -------------------------------- ### Prevent Duplicate Attribute Assignment with `initialize_with` Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/custom-construction/summary.md When `initialize_with` is used, attributes are assigned only in the constructor, preventing duplicate assignment. This example shows the behavior before version 4.0 where attributes were assigned twice. ```ruby FactoryBot.define do factory :user do initialize_with { new(name) } name { 'value' } end end build(:user) # runs User.new('value') ``` ```ruby FactoryBot.define do factory :user do initialize_with { new(name) } name { 'value' } end end build(:user) # runs user = User.new('value') user.name = 'value' ``` -------------------------------- ### Build Strategy: Pattern Matching Assignment Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Demonstrates using Ruby 3.0's pattern matching assignment with the `attributes_for` strategy. ```ruby # Integrates with Ruby 3.0's support for pattern matching assignment attributes_for(:user) => {email:, name:, **attrs} ``` -------------------------------- ### Equivalent ActiveRecord Operations Source: https://github.com/thoughtbot/factory_bot/wiki/How-factory_bot-interacts-with-ActiveRecord This demonstrates the underlying ActiveRecord operations that `create(:post)` performs, including creating and saving the associated user before the post. ```ruby user = User.new user.email = "person-1@example.com" user.save! post = Post.new post.title = "Hello" post.user = user post.save! ``` -------------------------------- ### Define Global and Factory-Scoped Sequences Source: https://context7.com/thoughtbot/factory_bot/llms.txt Define sequences to generate unique values across the test suite. Sequences can be global, factory-scoped, have custom starting values, aliases, or cycle through enumerables. ```ruby FactoryBot.define do # Global sequence — callable anywhere with generate(:email) sequence(:email) { |n| "user#{n}@example.com" } # Sequence with custom start value sequence(:order_number, 1000) { |n| "ORD-#{n}" } # Sequence without a block (auto-increments) sequence(:position) # Cyclic sequence using Enumerable sequence(:priority, %i[low medium high urgent].cycle) # Sequence with aliases (share the same counter) sequence(:token, aliases: [:access_token, :refresh_token]) { |n| "token-#{n}" } factory :user do email # implicit: calls generate(:email) sequence(:username) { |n| "user#{n}" } # factory-scoped inline sequence end factory :post do sequence(:title) { |n| "Post #{n}" } end end generate(:email) # => "user1@example.com" generate(:email) # => "user2@example.com" generate(:order_number) # => "ORD-1000" # Rewind all sequences back to their initial values FactoryBot.rewind_sequences generate(:email) # => "user1@example.com" ``` -------------------------------- ### Use FactoryBot Methods in Minitest::Spec Tests Source: https://github.com/thoughtbot/factory_bot/wiki/Integration:-Minitest::Spec After including the syntax methods, you can call FactoryBot's creation and building methods directly within your test cases. ```ruby it "renders itself" do user = create(:user, articles: build_list(:article, 2)) # not FactoryBot.create or FactoryBot.build_list writer = build(:writer) # not FactoryBot.build user.render(writer) _(writer.to_s).must_equal "User with two articles" end ``` -------------------------------- ### Create a User Pair Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Create a pair (two instances) of user records and save them to the database. Use when two persisted user records are needed. ```ruby created_users = create_pair(:user) ``` -------------------------------- ### Define traits for enum attributes Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/ref/traits_for_enum.md Use `traits_for_enum` to create traits for attributes that can take on specific values. This example shows defining traits for `:visibility` using an array and for `:collaborative` using a hash. ```ruby FactoryBot.define do factory :article do traits_for_enum :visibility, [:public, :private] # trait :public do # visibility { :public } # end # trait :private do # visibility { :private } # end traits_for_enum :collaborative, draft: 0, shared: 1 # trait :draft do # collaborative { 0 } # end # trait :shared do # collaborative { 1 } # end traits_for_enum :status # Article.statuses.each do |key, value| # trait key do # status { value } # end # end end end ``` -------------------------------- ### Helper Method for Has Many Associations Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/cookbook/has_many-associations.md Use a plain Ruby helper method to create a user and associated posts. This approach is simple and effective for straightforward cases. ```ruby FactoryBot.define do factory :post do title { "Through the Looking Glass" } user end factory :user do name { "Rachel Sanchez" } end end def user_with_posts(posts_count: 5) FactoryBot.create(:user) do |user| FactoryBot.create_list(:post, posts_count, user: user) end end create(:user).posts.length # 0 user_with_posts.posts.length # 5 user_with_posts(posts_count: 15).posts.length # 15 ``` -------------------------------- ### Define and use transient attributes in a trait Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/traits/with-transient-attributes.md Define transient attributes within a trait to pass temporary data to callbacks. The example shows how to define an `amount` transient attribute and use it in an `after(:create)` callback. ```ruby factory :invoice do trait :with_amount do transient do amount { 1 } end after(:create) do |invoice, context| create :line_item, invoice: invoice, amount: context.amount end end end create :invoice, :with_amount, amount: 2 ``` -------------------------------- ### Initialize with Attributes Hash Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/custom-construction/summary.md Pass all defined attributes as a hash to the constructor using `**attributes`. Transient attributes are excluded. This is useful for classes that accept keyword arguments in their initializer. ```ruby factory :user do transient do comments_count { 5 } end name "John Doe" initialize_with { new(**attributes) } end ``` -------------------------------- ### Reverting to Old Association Strategy Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/associations/build-strategies.md Set `FactoryBot.use_parent_strategy = false` to revert to the previous behavior where associations did not always match the parent object's strategy. This example demonstrates `create` and `build` with the old strategy. ```ruby FactoryBot.use_parent_strategy = false # Builds and saves a User and a Post post = create(:post) post.new_record? # => false post.author.new_record? # => false # Builds and saves a User, and then builds but does not save a Post post = build(:post) post.new_record? # => true post.author.new_record? # => false ``` -------------------------------- ### Build Factory Call Stack Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/activesupport-instrumentation/summary.md Use 'factory_bot.before_run_factory' and 'factory_bot.run_factory' subscriptions to build a call stack of factory creations. This is useful for debugging deeply nested associations. ```ruby factory_call_stack = [] ActiveSupport::Notifications.subscribe("factory_bot.before_run_factory") do |name, start, finish, id, payload| factory_call_stack.push(payload[:name]) end ActiveSupport::Notifications.subscribe("factory_bot.run_factory") do |name, start, finish, id, payload| factory_call_stack.pop end ``` -------------------------------- ### Include FactoryBot::Syntax::Methods in Minitest::Spec Source: https://github.com/thoughtbot/factory_bot/wiki/Integration:-Minitest::Spec Include this module to use FactoryBot methods like `create` and `build` directly within your Minitest::Spec tests. ```ruby class Minitest::Spec include FactoryBot::Syntax::Methods end ``` -------------------------------- ### Defining and Applying Traits Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/traits/defining-traits.md Define reusable attribute groups using `trait` and apply them to factories with the `traits` option. This example shows how to create traits for publishing status and duration, and then combine them to create specialized story factories. ```ruby factory :user, aliases: [:author] factory :story do title { "My awesome story" } author trait :published do published { true } end trait :unpublished do published { false } end trait :week_long_publishing do start_at { 1.week.ago } end_at { Time.now } end trait :month_long_publishing do start_at { 1.month.ago } end_at { Time.now } end factory :week_long_published_story, traits: [:published, :week_long_publishing] factory :month_long_published_story, traits: [:published, :month_long_publishing] factory :week_long_unpublished_story, traits: [:unpublished, :week_long_publishing] factory :month_long_unpublished_story, traits: [:unpublished, :month_long_publishing] end ``` -------------------------------- ### Run Full Test Suite Source: https://github.com/thoughtbot/factory_bot/blob/main/CONTRIBUTING.md Execute the default rake task to run the complete test suite and standard checks. ```sh bundle exec rake ``` -------------------------------- ### Define and Generate Global Sequences Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/sequences/generating.md Define a global sequence with an initial value and generate sequential strings. Use `generate` for a single value and `generate_list` for multiple values. ```ruby FactoryBot.define do sequence(:char, 'a') {|c| "global_character_#{c}" } factory :user do sequence(:name, %w[Jane Joe Josh Jayde John].to_enum) trait :with_age do sequence(:age, 21) end end end ``` ```ruby generate(:char) # "global_character_a" generate_list(:char, 2) # ["global_character_b", "global_character_c"] generate(:char) # "global_character_d" ``` ```ruby generate(:user, :name) # "Jane" generate_list(:user, :name, 3) # ['Joe', 'Josh', 'Jayde'] generate(:user, :name) # "John" ``` ```ruby generate(:user, :with_age, :age) # 21 generate_list(:user, :with_age, :age, 5) # [22, 23, 24, 25, 26] generate(:user, :with_age, :age) # 27 ``` -------------------------------- ### Include FactoryBot::Syntax::Methods in Minitest Source: https://github.com/thoughtbot/factory_bot/wiki/Integration:-minitest-rails Include this module in your ActiveSupport::TestCase to gain direct access to Factory Bot's creation methods. ```ruby class ActiveSupport::TestCase include FactoryBot::Syntax::Methods end ``` -------------------------------- ### Explicitly Setting Association Strategy to Build Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/associations/build-strategies.md To prevent an associated object from being saved, specify `strategy: :build` within the `association` declaration. This example shows how `build(:post)` affects both the post and its author when the strategy is explicitly set to build. ```ruby FactoryBot.use_parent_strategy = false factory :post do # ... association :author, factory: :user, strategy: :build end # Builds a User, and then builds a Post, but does not save either post = build(:post) post.new_record? # => true post.author.new_record? # => true ``` -------------------------------- ### Build User with Keyword Arguments Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md When keyword arguments correspond to local variable names, omit their values. ```ruby user = build(:user, account:, friends:) ``` -------------------------------- ### Handling Uniqueness Conflicts with Sequences Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/sequences/uniqueness.md When overriding a sequence value, ensure it does not conflict with existing data or other generated values to avoid uniqueness constraint errors. This example demonstrates a potential conflict where an explicit email override matches a generated email. ```ruby factory :user do sequence(:email) { |n| "person#{n}@example.com" } end FactoryBot.create(:user, email: "person1@example.com") FactoryBot.create(:user) ``` -------------------------------- ### Include FactoryBot Syntax in Test::Unit Source: https://github.com/thoughtbot/factory_bot/wiki/Integration:-Test::Unit Include `FactoryBot::Syntax::Methods` to use factory methods like `create` and `build` directly in your Test::Unit test cases. ```ruby class Test::Unit::TestCase include FactoryBot::Syntax::Methods end ``` -------------------------------- ### Build Associated Objects with Overrides Source: https://github.com/thoughtbot/factory_bot/blob/main/docs/src/associations/association-overrides.md Demonstrates building an 'author' object with a specific name and then building a 'post' object, explicitly associating it with the previously built 'author'. This shows how to control associated data. ```ruby eunji = build(:author, name: 'Eunji') post = build(:post, author: eunji) ``` -------------------------------- ### Configure Factory Bot for RSpec (Rails) Source: https://github.com/thoughtbot/factory_bot/wiki/Integration:-RSpec Include FactoryBot::Syntax::Methods in your RSpec configuration for Rails projects. Ensure this file is required in rails_helper.rb. ```ruby RSpec.configure do |config| config.include FactoryBot::Syntax::Methods end ``` -------------------------------- ### Include FactoryBot Syntax in Spinach Source: https://github.com/thoughtbot/factory_bot/wiki/Integration:-Spinach Include `FactoryBot::Syntax::Methods` to access FactoryBot's creation methods directly within your Spinach feature steps. This avoids the need to prefix methods with `FactoryBot::`. ```ruby class Spinach::FeatureSteps include FactoryBot::Syntax::Methods end ``` -------------------------------- ### Create Release Branch Source: https://github.com/thoughtbot/factory_bot/blob/main/RELEASING.md Use this command to create a new release branch from the main branch. ```shell git checkout main git pull git checkout -b release-x.x.x ``` -------------------------------- ### Include FactoryBot Syntax in Minitest Source: https://github.com/thoughtbot/factory_bot/wiki/Integration:-Minitest Include `FactoryBot::Syntax::Methods` in your Minitest::Test class to use FactoryBot methods directly. This makes test data creation more concise. ```ruby class Minitest::Test include FactoryBot::Syntax::Methods end ``` -------------------------------- ### Include FactoryBot Syntax in Minitest Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Include FactoryBot::Syntax::Methods to use factory methods directly within your Minitest::Unit::TestCase. ```ruby class Minitest::Unit::TestCase include FactoryBot::Syntax::Methods end ``` -------------------------------- ### Build a User Pair Source: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md Build a pair (two instances) of user records. Useful for scenarios requiring exactly two related or independent user objects. ```ruby built_users = build_pair(:user) ```