### Install factory_bot_rails for Rails Projects Source: https://thoughtbot.github.io/factory_bot/setup/summary Add the factory_bot_rails gem to your Gemfile for seamless integration with Rails applications. This is the recommended approach for Rails users. ```ruby gem "factory_bot_rails" ``` -------------------------------- ### Configure factory_bot with Test::Unit Source: https://thoughtbot.github.io/factory_bot/setup/summary Include FactoryBot::Syntax::Methods in your Test::Unit::TestCase classes to use factory_bot syntax in your unit tests. This provides a convenient way to generate test data. ```ruby class Test::Unit::TestCase include FactoryBot::Syntax::Methods end ``` -------------------------------- ### Configure factory_bot with RSpec Source: https://thoughtbot.github.io/factory_bot/setup/summary Include FactoryBot::Syntax::Methods in your RSpec configuration to enable factory_bot syntax within your tests. This allows you to use shorthand methods for creating factories. ```ruby RSpec.configure do |config| config.include FactoryBot::Syntax::Methods end ``` -------------------------------- ### Factory Bot Build Strategies Source: https://thoughtbot.github.io/factory_bot/print This snippet outlines the different build strategies supported by Factory Bot: `build`, `create`, `attributes_for`, and `build_stubbed`, with examples of their usage. ```ruby # Returns a User instance that's not saved user = build(:user) # Returns a saved User instance user = create(:user) # Returns a hash of attributes, which can be used to build a User instance for example attrs = attributes_for(:user) # Integrates with Ruby 3.0's support for pattern matching assignment attributes_for(:user) => {email:, name:, **attrs} # Returns an object with all defined attributes stubbed out stub = build_stubbed(:user) ``` -------------------------------- ### Install factory_bot for Non-Rails Projects Source: https://thoughtbot.github.io/factory_bot/setup/summary Add the core factory_bot gem to your Gemfile if you are not using the Rails framework. This allows you to use factory_bot in other Ruby projects. ```ruby gem "factory_bot" ``` -------------------------------- ### Example Rake Task for Factory Bot Linting Source: https://thoughtbot.github.io/factory_bot/print Provides an example of how to integrate `FactoryBot.lint` into a Rake task, which is a recommended practice for running factory checks before the test suite executes to avoid performance impacts on individual tests. ```ruby # Example Rake task: task lint_factories: :environment do begin FactoryBot.lint rescue FactoryBot::InvalidFactoryError => e puts "Factories are invalid:" e.failures.each do |failure| puts "- #{failure.name}: #{failure.exception.message}" end exit(1) end end ``` -------------------------------- ### Set and Generate User Email Sequence Values Source: https://thoughtbot.github.io/factory_bot/sequences/setting-the-value Illustrates how to generate a user email sequence, including setting a specific starting number using `FactoryBot.set_sequence`. ```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" ``` -------------------------------- ### Define Sequence with Aliases and Default Counter Source: https://thoughtbot.github.io/factory_bot/sequences/aliases This example demonstrates defining a sequence with aliases but using the default starting value (1) for the counter. The aliases 'sender' and 'receiver' will share this counter. ```ruby factory :user do sequence(:email, aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" } end ``` -------------------------------- ### Configure factory_bot Definition File Paths Source: https://thoughtbot.github.io/factory_bot/ref/find_definitions The load order for factory definitions can be customized by setting the `FactoryBot.definition_file_paths`. This can be done during application initialization, for example, in `config/initializers`, or through `Rails.application.config.factory_bot.definition_file_paths`. ```Ruby FactoryBot.definition_file_paths = [ "path/to/your/factories", "another/path/**/*.rb" ] ``` ```Ruby Rails.application.config.factory_bot.definition_file_paths = [ "config/factories", "app/models/factories/**/*.rb" ] ``` -------------------------------- ### Define Sequence with Aliases and Custom Start Value Source: https://thoughtbot.github.io/factory_bot/sequences/aliases This snippet shows how to define a sequence named 'email' with aliases 'sender' and 'receiver'. It starts the counter at 1000 and provides a block to generate email addresses. ```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) ``` -------------------------------- ### Rewind All FactoryBot Sequences Source: https://thoughtbot.github.io/factory_bot/print Demonstrates rewinding all global and factory-specific sequences to their starting values using `FactoryBot.rewind_sequences`. This is useful for resetting sequence states between tests. ```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" ``` -------------------------------- ### Use Symbol#to_proc for Callbacks Source: https://thoughtbot.github.io/factory_bot/print This example illustrates using `Symbol#to_proc` as a shorthand for defining callbacks, particularly for simple methods like `confirm!` on a user object. This makes the factory definition more compact. ```ruby # app/models/user.rb class User < ActiveRecord::Base def confirm! # confirm the user account end end # spec/factories.rb FactoryBot.define do factory :user do after :create, &:confirm! end end create(:user) # creates the user and confirms it ``` -------------------------------- ### Define Factory Inline Source: https://thoughtbot.github.io/factory_bot/using-without-bundler/summary This example shows how to define factories directly within your code. It requires the gem and uses the `FactoryBot.define` block to create a factory for a 'user' object with specific attributes. ```ruby require 'factory_bot' FactoryBot.define do factory :user do name { 'John Doe' } date_of_birth { 21.years.ago } end end ``` -------------------------------- ### Define user factory with aliases Source: https://thoughtbot.github.io/factory_bot/aliases/summary Defines a 'user' factory with aliases 'author' and 'commenter' for simplified association usage. This factory includes attributes for first name, last name, and date of birth. ```ruby factory :user, aliases: [:author, :commenter] do first_name { "John" } last_name { "Doe" } date_of_birth { 18.years.ago } end ``` -------------------------------- ### Define a factory with a sequence for email Source: https://thoughtbot.github.io/factory_bot/sequences/initial-value This snippet demonstrates how to define a factory for a 'user' with a sequence for the 'email' attribute. The sequence starts at 1000 and generates unique email addresses. ```ruby factory :user do sequence(:email, 1000) { |n| "person#{n}@example.com" } end ``` -------------------------------- ### factory_bot Callbacks: Global, Factory, and Trait Order Source: https://thoughtbot.github.io/factory_bot/callbacks/callback_order Demonstrates the execution order of factory_bot callbacks including global, factory-specific, and trait-specific callbacks. This example highlights how callbacks are nested and executed based on their definition scope. ```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) ``` -------------------------------- ### Use alias for user association in post factory Source: https://thoughtbot.github.io/factory_bot/aliases/summary Demonstrates using the 'author' alias to associate a 'user' with a 'post' factory. This replaces the need for a full 'association' declaration. ```ruby factory :post do # The alias allows us to write author instead of # association :author, factory: :user author title { "How to read a book effectively" } body { "There are five steps involved." } end ``` -------------------------------- ### Use alias for user association in comment factory Source: https://thoughtbot.github.io/factory_bot/aliases/summary Shows how to utilize the 'commenter' alias to associate a 'user' with a 'comment' factory, simplifying the association syntax. ```ruby factory :comment do # The alias allows us to write commenter instead of # association :commenter, factory: :user commenter body { "Great article!" } end ``` -------------------------------- ### Selectively lint factories Source: https://thoughtbot.github.io/factory_bot/linting-factories/summary This example shows how to lint specific factories by filtering the available factories. Here, factories prefixed with 'old_' are excluded from the linting process. ```ruby factories_to_lint = FactoryBot.factories.reject do |factory| factory.name =~ /^old_/ end FactoryBot.lint factories_to_lint ``` -------------------------------- ### Explicitly Specify Factory Class Source: https://thoughtbot.github.io/factory_bot/print This example shows how to explicitly define the class for a factory. This is useful when the factory name doesn't directly map to the desired class name. ```ruby # This will use the User class (otherwise Admin would have been guessed) factory :admin, class: "User" ``` -------------------------------- ### Attribute Setter Example in Ruby Source: https://thoughtbot.github.io/factory_bot/ref/add_attribute Illustrates the direct use of a Ruby attribute setter, which is how `add_attribute` functions internally. This shows the assignment of a value to the 'name' attribute of a User object. ```ruby user = User.new user.name = "Acid Burn" ``` -------------------------------- ### Generating a Single Sequence Value Source: https://thoughtbot.github.io/factory_bot/print Demonstrates the `generate` method for retrieving a single value from a sequence. This is the primary way to interact with sequences to get their next value. ```ruby generate(:email) # => "person1@example.com" generate(:email) # => "person2@example.com" ``` -------------------------------- ### factory_bot Callbacks: Inheritance and Nested Traits Order Source: https://thoughtbot.github.io/factory_bot/callbacks/callback_order Illustrates the callback execution order in a more complex scenario involving factory inheritance and multiple nested traits. This example showcases how callbacks from global, parent, child factories, and various traits are sequenced. ```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) ``` -------------------------------- ### Overriding Attributes on Associations (Ruby) Source: https://thoughtbot.github.io/factory_bot/print Explains how to override attributes on associations, providing examples for implicit, explicit, and inline methods. This allows customization of associated objects. ```ruby factory :post do # ... author factory: :author, last_name: "Writely" end factory :post do # ... association :author, last_name: "Writely" end factory :post do # ... author_last_name { "Writely" } author { association :author, last_name: author_last_name } end ``` -------------------------------- ### Linking Associated Objects with Attribute Overrides (Ruby) Source: https://thoughtbot.github.io/factory_bot/print Shows how attribute overrides can be used to link associated objects. This includes examples using direct association and overriding attributes of 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) ``` ```ruby author = build(:author, name: 'Eunji') post = build(:post, author:) ``` -------------------------------- ### Sequence Incrementing Without a Block Source: https://thoughtbot.github.io/factory_bot/print Illustrates a sequence that automatically increments its value without needing a custom block. It starts from its initial value (defaulting to 1 if not specified) and increments on each call. ```ruby factory :post do sequence(:position) end ``` -------------------------------- ### Manage Model Callbacks within Factory Definitions Source: https://thoughtbot.github.io/factory_bot/callbacks/summary This example demonstrates how to temporarily disable a model's 'after_create' callback before a factory is created and then re-enable it afterwards. This is useful for preventing unintended side effects during factory operations. ```ruby factory :user do before(:all){ User.skip_callback(:create, :after, :send_welcome_email) } after(:all){ User.set_callback(:create, :after, :send_welcome_email) } end ``` -------------------------------- ### Generate Has-Many Data with Transient Attributes and Inline Associations Source: https://thoughtbot.github.io/factory_bot/cookbook/has_many-associations This example combines transient attributes with inline associations for more flexible generation of has-many relationships. The `user_with_posts` factory includes a `posts_count` transient attribute, and the `posts` association uses `Array.new` to create the specified number of associated posts. This method is versatile for use with `create`, `build`, and `build_stubbed`. ```ruby FactoryBot.define do factory :post do title { "Through the Looking Glass" } user end factory :user do name { "Adiza Kumato" } factory :user_with_posts do transient do posts_count { 5 } end posts do Array.new(posts_count) { association(:post) } end end end end create(:user_with_posts).posts.length # 5 create(:user_with_posts, posts_count: 15).posts.length # 15 build(:user_with_posts, posts_count: 15).posts.length # 15 build_stubbed(:user_with_posts, posts_count: 15).posts.length # 15 ``` -------------------------------- ### Using Traits with Different Association Names in factory_bot Source: https://thoughtbot.github.io/factory_bot/traits/with-associations This example demonstrates using traits with associations where the association name differs from the factory name. It defines a user factory with an admin trait and a post factory associating with an 'author' that uses the user factory with the admin trait. Two syntaxes are shown for applying the trait. ```ruby factory :user do name { "Friendly User" } trait :admin do admin { true } end end factory :post do association :author, :admin, factory: :user, name: 'John Doe' # or association :author, factory: [:user, :admin], name: 'John Doe' end # creates an admin user with name "John Doe" create(:post).author ``` -------------------------------- ### factory_bot Create Strategy Source: https://thoughtbot.github.io/factory_bot/print The `FactoryBot.create` method constructs an instance of the class and then persists it. It supports similar build strategies as `FactoryBot.build` (single, pair, list) and includes hooks for the creation process (`after_build`, `before_create`, `to_create`, `after_create`). ```ruby FactoryBot.create(:user) FactoryBot.create(:user, :admin, name: "John Doe") FactoryBot.create_list(:user, 5) FactoryBot.create_list(:user, 5, name: "Jane Doe") FactoryBot.create_pair(:user) ``` -------------------------------- ### Define a Factory with factory_bot Source: https://thoughtbot.github.io/factory_bot/ref/factory Demonstrates the basic syntax for defining a factory using `FactoryBot.define`. It shows how to specify the factory name and use a block to define its attributes. The `:class` option is used to specify the object the factory should build. ```ruby FactoryBot.define do factory :user do name { "John Doe" } email { "john.doe@example.com" } factory :admin, class: "AdminUser" do role { "admin" } end end end ``` -------------------------------- ### Lint all factories with factory_bot Source: https://thoughtbot.github.io/factory_bot/linting-factories/summary This snippet demonstrates the basic usage of `FactoryBot.lint` to create each factory and catch exceptions. It's recommended to run this before your test suite. ```ruby FactoryBot.lint ``` -------------------------------- ### Custom Initialization with User.build_with_name Source: https://thoughtbot.github.io/factory_bot/custom-construction/summary Shows how to use `initialize_with` to call a custom class method, `User.build_with_name`, for object instantiation. This allows for more complex object creation logic beyond a simple `new` call. ```Ruby factory :user do name { "John Doe" } initialize_with { User.build_with_name(name) } end ``` -------------------------------- ### Generate Data with FactoryBot Source: https://thoughtbot.github.io/factory_bot/print Demonstrates basic data generation using `generate` and `generate_list` for different attributes and types. ```ruby generate(:char) # "global_character_a" generate_list(:char, 2) # ["global_character_b", "global_character_c"] generate(:char) # "global_character_d" generate(:user, :name) # "Jane" generate_list(:user, :name, 3) # ['Joe', 'Josh', 'Jayde'] generate(:user, :name) # "John" generate(:user, :with_age, :age) # 21 generate_list(:user, :with_age, :age, 5) # [22, 23, 24, 25, 26] generate(:user, :with_age, :age) # 27 ``` -------------------------------- ### FactoryBot Traits with Instance Creation Source: https://thoughtbot.github.io/factory_bot/print Explains how to pass traits as symbols during instance creation (build, create, etc.) to apply specific configurations and overrides. ```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") ``` ```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") ``` -------------------------------- ### factory_bot Create Method Source: https://thoughtbot.github.io/factory_bot/ref/build-strategies Explains the `FactoryBot.create` method for constructing and persisting objects. It details the hooks invoked during creation (`after_build`, `before_create`, `to_create`, `after_create`) and how the `to_create` hook controls persistence, defaulting to `#save!`. ```ruby user = UserFactory.create admin = UserFactory.create(:admin) user = UserFactory.create({ name: "John Doe" }) user = UserFactory.create(:admin, { name: "Jane Doe" }) user = UserFactory.create do |u| u.name = "John Doe" end users = UserFactory.create_list(5) users = UserFactory.create_list(5, :admin) users = UserFactory.create_list(5, { name: "John Doe" }) users = UserFactory.create_list(5, :admin, { name: "Jane Doe" }) users = UserFactory.create_list(5) do |u, i| u.name = "User #{i}" end UserFactory.to_create do |user_instance| user_instance.save end ``` -------------------------------- ### factory_bot Build Strategies Source: https://thoughtbot.github.io/factory_bot/ref/build-strategies Demonstrates how to construct instances using factory_bot's built-in build strategies like .build, .build_pair, and .build_list. These methods accept factory names, traits, and attribute overrides, and can also take a block for post-construction manipulation. They utilize ActiveSupport::Notifications for instrumentation. ```ruby user = UserFactory.build admin = UserFactory.build(:admin) user = UserFactory.build({ name: "John Doe" }) user = UserFactory.build(:admin, { name: "Jane Doe" }) user = UserFactory.build do |u| u.name = "John Doe" end users = UserFactory.build_list(5) users = UserFactory.build_list(5, :admin) users = UserFactory.build_list(5, { name: "John Doe" }) users = UserFactory.build_list(5, :admin, { name: "Jane Doe" }) users = UserFactory.build_list(5) do |u, i| u.name = "User #{i}" end ``` -------------------------------- ### factory_bot: initialize_with default definition Source: https://thoughtbot.github.io/factory_bot/ref/build-and-create The `initialize_with` method defines how an object instance is created for a factory. It accepts a block that can access the factory's attributes and is used to return a new instance of the object. ```ruby initialize_with { new } ``` -------------------------------- ### Setting up Associations in Factories (Ruby) Source: https://thoughtbot.github.io/factory_bot/print Explains how to set up associations within factories. If the factory name matches the association name, the factory name can be omitted. ```ruby factory :post do # ... author end ``` -------------------------------- ### Use FactoryBot callbacks for build strategies Source: https://thoughtbot.github.io/factory_bot/print Callbacks like `after`, `before`, and `callback` allow hooking into FactoryBot's build process. They can be scoped to a specific factory or global. Callbacks receive the factory instance and the context, including transient attributes. ```ruby factory :user do after(:create) do |user, context| user.post_first_article(context.article) end callback(:after_create) do |user, context| user.post_first_article(context.article) end end ``` -------------------------------- ### Define Factory Bot Sequences and Factories Source: https://thoughtbot.github.io/factory_bot/sequences/setting-the-value Defines global sequences and factory sequences for 'user' with traits for email. This sets up the data structures for generating test data. ```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 ``` -------------------------------- ### Referencing Sequences by URI (Resource String) Source: https://thoughtbot.github.io/factory_bot/print Demonstrates referencing a sequence using a single string formatted as a URI, with names separated by forward slashes. This provides a concise way to specify the sequence. ```ruby generate("my_factory_name/my_trait_name/my_sequence_name") ``` -------------------------------- ### Using after and callback for after_create Source: https://thoughtbot.github.io/factory_bot/ref/hooks Demonstrates how to use the `after` and `callback` methods in factory_bot to execute code after a record is created. The `after` method provides a more concise syntax for common callbacks like `after(:create)`. Both methods accept a block that receives the created instance and a context object. The context can hold transient attributes passed during factory creation. ```ruby after(:create) do |user, context| user.post_first_article(context.article) end callback(:after_create) do |user, context| user.post_first_article(context.article) end ``` -------------------------------- ### factory_bot Build Strategy Source: https://thoughtbot.github.io/factory_bot/print The `FactoryBot.build` method constructs an instance of the class. It can build single instances, pairs, or lists of instances. It also supports traits, overrides, and blocks for further customization. ```ruby FactoryBot.build(:user) FactoryBot.build(:user, :admin, name: "John Doe") FactoryBot.build_list(:user, 5) FactoryBot.build_list(:user, 5, name: "Jane Doe") FactoryBot.build_pair(:user) ``` -------------------------------- ### Global initialize_with for All Factories Source: https://thoughtbot.github.io/factory_bot/custom-construction/summary Demonstrates how to set a default `initialize_with` behavior for all factories defined within a `FactoryBot.define` block. This is useful for applying consistent instantiation logic across your project. ```Ruby FactoryBot.define do initialize_with { new("Awesome first argument") } end ``` -------------------------------- ### Register custom FactoryBot build strategies Source: https://thoughtbot.github.io/factory_bot/print Add new build strategies by calling `FactoryBot.register_strategy`. The provided class must implement `association` and `result` methods. `association` handles building associated records, and `result` returns the final object. ```ruby class MyStrategy def self.call(runner) # Build logic runner.run(:build) end def self.association(runner) runner.run(:build) end def self.result(object) object end end FactoryBot.register_strategy(:my_strategy, MyStrategy) ``` -------------------------------- ### Define and Generate Sequences in factory_bot Source: https://thoughtbot.github.io/factory_bot/sequences/generating Demonstrates defining sequences for characters and user attributes (name, age) and then generating single values or lists of these sequences using `generate` and `generate_list`. ```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 ## # char generate(:char) # "global_character_a" generate_list(:char, 2) # ["global_character_b", "global_character_c"] generate(:char) # "global_character_d" ## # user name generate(:user, :name) # "Jane" generate_list(:user, :name, 3) # ['Joe', 'Josh', 'Jayde'] generate(:user, :name) # "John" ## # user age generate(:user, :with_age, :age) # 21 generate_list(:user, :with_age, :age, 5) # [22, 23, 24, 25, 26] generate(:user, :with_age, :age) # 27 ``` -------------------------------- ### Factory Options in factory_bot Source: https://thoughtbot.github.io/factory_bot/ref/factory Illustrates how to configure factory behavior using options like `:parent`, `:aliases`, and `:traits`. The `:parent` option allows for inheritance, `:aliases` provide alternative names for a factory, and `:traits` define reusable sets of attributes. ```ruby FactoryBot.define do factory :post, parent: :published_post, aliases: [:article] do title { "My First Post" } trait :draft do published_at { nil } end end end ``` -------------------------------- ### factory_bot: to_create default definition Source: https://thoughtbot.github.io/factory_bot/ref/build-and-create The `to_create` method customizes the `FactoryBot.create` strategy. It takes a block that receives the constructed object and the factory_bot context, allowing control over persistence, with the default being to save the object. ```ruby to_create { |obj, context| obj.save! } ``` -------------------------------- ### Set and Generate User Name Sequence Values Source: https://thoughtbot.github.io/factory_bot/sequences/setting-the-value Shows how to generate a user name sequence and then set it to a specific value using `FactoryBot.set_sequence`. ```ruby # user name generate(:user, :name) # "Jane" FactoryBot.set_sequence(:user, :name, 'Jayde') generate(:user, :name) # "Jayde" ``` -------------------------------- ### Referencing Sequences by URI (Strings) Source: https://thoughtbot.github.io/factory_bot/print Illustrates referencing a sequence by providing its constituent names (factory, trait, sequence) as individual strings to the `generate` method. ```ruby generate('my_factory_name', 'my_trait_name', 'my_sequence_name') ``` -------------------------------- ### Define Factories and Build Objects with Overrides (Ruby) Source: https://thoughtbot.github.io/factory_bot/associations/association-overrides Demonstrates defining factories for 'author' and 'post' and then building instances with attribute overrides. Shows how 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) ``` -------------------------------- ### Referencing Sequences by URI (Symbols) Source: https://thoughtbot.github.io/factory_bot/print Shows how to reference a sequence using its factory name, trait name (if applicable), and sequence name, all provided as individual symbols to the `generate` method. ```ruby generate(:my_factory_name, :my_trait_name, :my_sequence_name) ``` -------------------------------- ### factory_bot Build Strategies: build, create, attributes_for, build_stubbed Source: https://thoughtbot.github.io/factory_bot/using-factories/build-strategies Demonstrates the usage of factory_bot's core build strategies. `build` creates an unsaved instance, `create` saves an instance to the database, `attributes_for` returns a hash of attributes, and `build_stubbed` creates an object with stubbed attributes. Blocks can be passed to yield the created object for further manipulation. ```ruby user = build(:user) user = create(:user) attrs = attributes_for(:user) attributes_for(:user) => {email:, name:, **attrs} stub = build_stubbed(:user) create(:user) do |user| user.posts.create(attributes_for(:post)) end ``` -------------------------------- ### Sequence with Enumerable and Cycle Source: https://thoughtbot.github.io/factory_bot/print Demonstrates using an Enumerable (an array of symbols) with the `.cycle` method as the source for a sequence. This allows generating values by cycling through a predefined list. ```ruby factory :task do sequence :priority, %i[low medium high urgent].cycle end ``` -------------------------------- ### Registering a Build Strategy with factory_bot Source: https://thoughtbot.github.io/factory_bot/ref/register_strategy Demonstrates how to add a new build strategy to factory_bot. The `register_strategy` method accepts a symbol for the strategy name and a class that defines `association` and `result` methods. ```ruby FactoryBot.register_strategy(:my_strategy, MyStrategyClass) ``` -------------------------------- ### Initializing with Attributes Hash using **attributes Source: https://thoughtbot.github.io/factory_bot/custom-construction/summary Illustrates how to pass all defined factory attributes, excluding transient ones, to the constructor using `new(**attributes)`. This is a convenient way to initialize objects with multiple attributes. ```Ruby factory :user do transient do comments_count { 5 } end name "John Doe" initialize_with { new(**attributes) } end ``` -------------------------------- ### Define Global Callbacks Source: https://thoughtbot.github.io/factory_bot/print Shows how to define callbacks that apply globally to all factories by placing them within a `FactoryBot.define` block. These global callbacks execute before or after factory-specific or trait callbacks. ```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 ``` -------------------------------- ### Custom Object Initialization with `initialize_with` Source: https://thoughtbot.github.io/factory_bot/print Demonstrates overriding the default object initialization behavior using `initialize_with`. This is useful for non-ActiveRecord objects that require arguments in their `initialize` method. ```ruby # user.rb class User attr_accessor :name, :email def initialize(name) @name = name end end # factories.rb sequence(:email) { |n| "person#{n}@example.com" } factory :user do name { "Jane Doe" } email initialize_with { new(name) } end build(:user).name # Jane Doe ``` -------------------------------- ### Create with Block - FactoryBot Source: https://thoughtbot.github.io/factory_bot/print Demonstrates creating an instance of a factory and yielding the created object to a block for further modifications. This allows for nested object creation or attribute setting within the yielded object. ```ruby create(:user) do |user| user.posts.create(attributes_for(:post)) end ``` -------------------------------- ### Optimized Initialization with initialize_with (No Duplicate Assignment) Source: https://thoughtbot.github.io/factory_bot/custom-construction/summary Explains how `initialize_with` prevents duplicate assignment by only passing attributes to the constructor. This behavior is demonstrated with a `User` factory, showing the optimized instantiation flow compared to older versions. ```Ruby FactoryBot.define do factory :user do initialize_with { new(name) } name { 'value' } end end build(:user) # runs User.new('value') ``` -------------------------------- ### FactoryBot Sequences with Scopes Source: https://thoughtbot.github.io/factory_bot/print Illustrates how to use sequences with scopes to ensure proper value generation, especially when attributes depend on other factory attributes or external objects. ```ruby FactoryBot.define do factory :user do sequence(:email) { |n| "#{name}-#{n}@example.com" } end end jester = build(:user, name: "Jester") jester.email # "Jester-1@example.com" generate(:user, :email, scope: jester) # "Jester-2@example.com" generate_list(:user, :email, 2, scope: jester) # ["Jester-3@example.com", "Jester-4@example.com"] ``` ```ruby require 'ostruct' FactoryBot.define do factory :user do sequence(:info) { |n| "#{name}-#{n}-#{age + n}" } end end test_scope = OpenStruct.new(name: "Jester", age: 23) generate_list('user/info', 3, scope: test_scope) # ["Jester-1-24", "Jester-2-25", "Jester-3-26"] ``` -------------------------------- ### Define Factory with after(:build) Callback Source: https://thoughtbot.github.io/factory_bot/callbacks/summary This snippet shows how to define a factory named 'user' that executes a 'generate_hashed_password' method after the user object is built. The 'after(:build)' callback receives the built object and a context object. ```ruby factory :user do after(:build) { |user, context| generate_hashed_password(user) } end ``` -------------------------------- ### Create Multiple Factory Instances (build_list, create_list) Source: https://thoughtbot.github.io/factory_bot/building-or-creating-multiple-records/summary Use build_list and create_list to generate multiple factory instances. You can pass a hash to set attributes for all instances or a block to customize each instance individually. `create_list` saves instances before yielding them. ```Ruby built_users = build_list(:user, 25) created_users = create_list(:user, 25) ``` ```Ruby twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago) ``` ```Ruby twenty_somethings = build_list(:user, 10) do |user, i| user.date_of_birth = (20 + i).years.ago end ``` ```Ruby twenty_somethings = create_list(:user, 10) do |user, i| user.date_of_birth = (20 + i).years.ago user.save! end ``` -------------------------------- ### Nesting Factories for Reusability (Ruby) Source: https://thoughtbot.github.io/factory_bot/print Illustrates how to create multiple factories for the same class without repeating common attributes by nesting factories. This promotes code reuse and organization. ```ruby factory :post do title { "A title" } factory :approved_post do approved { true } end end approved_post = create(:approved_post) approved_post.title # => "A title" approved_post.approved # => true ``` -------------------------------- ### Define and Register Custom Strategy with Callbacks (Ruby) Source: https://thoughtbot.github.io/factory_bot/custom-callbacks/summary Demonstrates how to create a custom strategy named 'json' that includes before, after, and custom callbacks. It registers this strategy with FactoryBot and defines a factory that utilizes these callbacks. ```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 ``` -------------------------------- ### factory_bot Null Method Source: https://thoughtbot.github.io/factory_bot/ref/build-strategies Explains the `FactoryBot.null` method, which returns `nil`. It also covers `null_pair` for a pair of nils and `null_list` for multiple nils, noting its internal usage. ```ruby nil_value = FactoryBot.null nil_pair = FactoryBot.null_pair nil_list = FactoryBot.null_list(3) ``` -------------------------------- ### Generate Has-Many Data with Plain Ruby Helper Source: https://thoughtbot.github.io/factory_bot/cookbook/has_many-associations This method uses a plain Ruby helper to create associated records. It defines factories for 'post' and 'user' and then a helper function 'user_with_posts' to create a user and a specified number of posts associated with that user. It's a straightforward way to set up relationships. ```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 ``` -------------------------------- ### Customize Factory Definition Paths Source: https://thoughtbot.github.io/factory_bot/using-without-bundler/summary This snippet illustrates how to specify custom directories for factory definitions if they are not in the default locations. After setting the paths, `find_definitions` will load from the specified directories. ```ruby FactoryBot.definition_file_paths = %w(custom_factories_directory) FactoryBot.find_definitions ``` -------------------------------- ### Define Multiple Callback Types - factory_bot Source: https://thoughtbot.github.io/factory_bot/callbacks/multiple-callbacks Demonstrates how to define different types of callbacks (after build and after create) on the same factory. This allows for specific actions to be performed after object instantiation and after object persistence. ```ruby factory :user do after(:build) { |user| do_something_to(user) } after(:create) { |user| do_something_else_to(user) } end ``` -------------------------------- ### Load factory_bot Definitions Source: https://thoughtbot.github.io/factory_bot/ref/find_definitions The `FactoryBot.find_definitions` method is used to load all factory definitions within a project. The order in which these definitions are loaded is determined by the `FactoryBot.definition_file_paths` attribute, which can be configured. ```Ruby FactoryBot.find_definitions ``` -------------------------------- ### Set and Generate Global Sequence Values Source: https://thoughtbot.github.io/factory_bot/sequences/setting-the-value Demonstrates how to generate a global sequence value and then set it to a specific value using `FactoryBot.set_sequence`. ```ruby # char generate(:char) # "global_character_a" FactoryBot.set_sequence(:char, 'z') generate(:char) # "global_character_z" ``` -------------------------------- ### Basic Factory Definition for User Source: https://thoughtbot.github.io/factory_bot/print This is a simple Factory Bot definition for a 'user' factory. It sets attributes like first name, last name, and admin status. ```ruby # This will guess the User class FactoryBot.define do factory :user do first_name { "John" } last_name { "Doe" } admin { false } end end ``` -------------------------------- ### Define Multiple Callbacks for Multiple Strategies - factory_bot Source: https://thoughtbot.github.io/factory_bot/callbacks/multiple-callbacks Illustrates defining multiple callbacks for various strategies (stub, create, custom) within a single factory definition. This is useful for executing common code across different building strategies. ```ruby factory :user do callback(:after_stub, :before_create) { do_something } after(:stub, :create) { do_something_else } before(:create, :custom) { do_a_third_thing } end ``` -------------------------------- ### Directly Generate Sequence Values Source: https://thoughtbot.github.io/factory_bot/print Explains how to directly generate single values or arrays of sequential values using `:generate` and `:generate_list` without building a full object. This speeds up testing by focusing only on sequence generation. ```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 ``` -------------------------------- ### Callback Execution Order with Global, Factory, and Trait Callbacks Source: https://thoughtbot.github.io/factory_bot/print This snippet details the execution order of callbacks when multiple are defined at different levels (global, factory, trait). It demonstrates how `before` and `after` callbacks are interleaved, respecting the hierarchy and order of trait application. ```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)" ``` -------------------------------- ### Basic User Initialization with initialize_with Source: https://thoughtbot.github.io/factory_bot/custom-construction/summary Demonstrates overriding the default `new` behavior to pass the `name` attribute to the `User` class's `initialize` method. This is useful for non-ActiveRecord objects requiring constructor arguments. ```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 ```