Skip to content

Commit

Permalink
Merge pull request rails#48512 from zzak/fixtures-docs
Browse files Browse the repository at this point in the history
Update documentation around fixture paths
  • Loading branch information
zzak authored Jun 20, 2023
2 parents 162c4b4 + 9cdc347 commit c25cc2e
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 30 deletions.
13 changes: 9 additions & 4 deletions actionmailer/lib/action_mailer/test_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ def determine_default_mailer(name)
end
end

# Reads the fixture file for the given mailer.
#
# This is useful when testing mailers by being able to write the body of
# an email inside a fixture. See the testing guide for a concrete example:
# https://guides.rubyonrails.org/testing.html#revenge-of-the-fixtures
def read_fixture(action)
IO.readlines(File.join(Rails.root, "test", "fixtures", self.class.mailer_class.name.underscore, action))
end

private
def initialize_test_deliveries
set_delivery_method :test
Expand Down Expand Up @@ -110,10 +119,6 @@ def charset
def encode(subject)
Mail::Encodings.q_value_encode(subject, charset)
end

def read_fixture(action)
IO.readlines(File.join(Rails.root, "test", "fixtures", self.class.mailer_class.name.underscore, action))
end
end

include Behavior
Expand Down
58 changes: 35 additions & 23 deletions activerecord/lib/active_record/fixtures.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
#
# \Fixtures are a way of organizing data that you want to test against; in short, sample data.
#
# They are stored in YAML files, one file per model, which are placed in the directories
# appointed by <tt>ActiveSupport::TestCase.fixture_paths=(path)</tt> (this is automatically
# configured for Rails, so you can just put your files in <tt><your-rails-app>/test/fixtures/</tt>,
# or in the <tt>test/fixtures</tt> folder under any of your application's engines).
# They are stored in YAML files, one file per model, which are by default placed in either
# <tt><your-rails-app>/test/fixtures/</tt> or in the <tt>test/fixtures</tt>
# folder under any of your application's engines.
#
# The location can also be changed with ActiveSupport::TestCase.fixture_paths=,
# once you have <tt>require "rails/test_help"</tt> in your +test_helper.rb+.
#
# The fixture file ends with the +.yml+ file extension, for example:
# <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
#
Expand All @@ -42,10 +45,17 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
# is followed by an indented list of key/value pairs in the "key: value" format. Records are
# separated by a blank line for your viewing pleasure.
#
# Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
# See https://yaml.org/type/omap.html
# for the specification. You will need ordered fixtures when you have foreign key constraints
# on keys in the same table. This is commonly needed for tree structures. Example:
# == Ordering
#
# Fixtures by default are unordered. This is because the maps in YAML are unordered.
#
# If you want ordered fixtures, use the omap YAML type.
# See https://yaml.org/type/omap.html for the specification.
#
# You will need ordered fixtures when you have foreign key constraints
# on keys in the same table. This is commonly needed for tree structures.
#
# For example:
#
# --- !omap
# - parent:
Expand All @@ -57,7 +67,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
# parent_id: 1
# title: Child
#
# = Using Fixtures in Test Cases
# == Using Fixtures in Test Cases
#
# Since fixtures are a testing construct, we use them in our unit and functional tests. There
# are two ways to use the fixtures, but first let's take a look at a sample unit test:
Expand Down Expand Up @@ -127,7 +137,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
# traversed in the database to create the fixture hash and/or instance variables. This is expensive for
# large sets of fixtured data.
#
# = Dynamic fixtures with ERB
# == Dynamic fixtures with \ERB
#
# Sometimes you don't care about the content of the fixtures as much as you care about the volume.
# In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load
Expand Down Expand Up @@ -165,7 +175,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
# name: kitten.png
# sha: <%= file_sha 'files/kitten.png' %>
#
# = Transactional Tests
# == Transactional Tests
#
# Test cases can use begin+rollback to isolate their changes to the database instead of having to
# delete+insert for every test case.
Expand Down Expand Up @@ -201,7 +211,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
# 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM.
# Use InnoDB, MaxDB, or NDB instead.
#
# = Advanced Fixtures
# == Advanced Fixtures
#
# Fixtures that don't specify an ID get some extra features:
#
Expand All @@ -215,7 +225,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
# * Fixture label interpolation
# * Support for YAML defaults
#
# == Stable, Autogenerated IDs
# === Stable, Autogenerated IDs
#
# Here, have a monkey fixture:
#
Expand Down Expand Up @@ -244,13 +254,13 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
# The generated ID for a given label is constant, so we can discover
# any fixture's ID without loading anything, as long as we know the label.
#
# == Label references for associations (+belongs_to+, +has_one+, +has_many+)
# === Label references for associations (+belongs_to+, +has_one+, +has_many+)
#
# Specifying foreign keys in fixtures can be very fragile, not to
# mention difficult to read. Since Active Record can figure out the ID of
# any fixture from its label, you can specify FK's by label instead of ID.
#
# === +belongs_to+
# ==== +belongs_to+
#
# Let's break out some more monkeys and pirates.
#
Expand Down Expand Up @@ -314,9 +324,9 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
#
# Just provide the polymorphic target type and Active Record will take care of the rest.
#
# === +has_and_belongs_to_many+ or <tt>has_many :through</tt>
# ==== +has_and_belongs_to_many+ or <tt>has_many :through</tt>
#
# Time to give our monkey some fruit.
# \Time to give our monkey some fruit.
#
# ### in monkeys.yml
#
Expand Down Expand Up @@ -378,15 +388,15 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
# the fixture's model class and discovers the +has_and_belongs_to_many+
# associations.
#
# == Autofilled Timestamp Columns
# === Autofilled \Timestamp Columns
#
# If your table/model specifies any of Active Record's
# standard timestamp columns (+created_at+, +created_on+, +updated_at+, +updated_on+),
# they will automatically be set to <tt>Time.now</tt>.
#
# If you've set specific values, they'll be left alone.
#
# == Fixture label interpolation
# === Fixture label interpolation
#
# The label of the current fixture is always available as a column value:
#
Expand All @@ -407,7 +417,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
#
# ActiveRecord::FixtureSet.identify(:boaty_mcboatface, :uuid)
#
# == Support for YAML defaults
# === Support for YAML defaults
#
# You can set and reuse defaults in your fixtures YAML file.
# This is the same technique used in the +database.yml+ file to specify
Expand Down Expand Up @@ -583,7 +593,8 @@ def create_fixtures(fixtures_directories, fixture_set_names, class_names = {}, c
end

# Returns a consistent, platform-independent identifier for +label+.
# Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
#
# \Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
def identify(label, column_type = :integer)
if column_type == :uuid
Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
Expand All @@ -596,15 +607,16 @@ def identify(label, column_type = :integer)
# between the label and the subcomponents of the provided composite key.
#
# Example:
# composite_identify("label", [:a, :b, :c]) => { a: hash_1, b: hash_2, c: hash_3 }
#
# composite_identify("label", [:a, :b, :c]) => { a: hash_1, b: hash_2, c: hash_3 }
def composite_identify(label, key)
key
.index_with
.with_index { |sub_key, index| (identify(label) << index) % MAX_ID }
.with_indifferent_access
end

# Superclass for the evaluation contexts used by ERB fixtures.
# Superclass for the evaluation contexts used by \ERB fixtures.
def context_class
@context_class ||= Class.new
end
Expand Down
16 changes: 13 additions & 3 deletions activerecord/lib/active_record/test_fixtures.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ def after_teardown # :nodoc:
end

included do
##
# :singleton-method: fixture_paths
#
# Returns the ActiveRecord::FixtureSet collection

##
# :singleton-method: fixture_paths=
#
# :call-seq:
# fixture_paths=(fixture_paths)
class_attribute :fixture_paths, instance_writer: false, default: []
class_attribute :fixture_table_names, default: []
class_attribute :fixture_class_names, default: {}
Expand All @@ -42,7 +52,7 @@ def set_fixture_class(class_names = {})
self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
end

def fixture_path
def fixture_path # :nodoc:
ActiveRecord.deprecator.warn(<<~WARNING)
TestFixtures.fixture_path is deprecated and will be removed in Rails 7.2. Use .fixture_paths instead.
If multiple fixture paths have been configured with .fixture_paths, then .fixture_path will just return
Expand All @@ -51,7 +61,7 @@ def fixture_path
fixture_paths.first
end

def fixture_path=(path)
def fixture_path=(path) # :nodoc:
ActiveRecord.deprecator.warn("TestFixtures.fixture_path= is deprecated and will be removed in Rails 7.2. Use .fixture_paths= instead.")
self.fixture_paths = Array(path)
end
Expand Down Expand Up @@ -99,7 +109,7 @@ def uses_transaction?(method)
end
end

def fixture_path
def fixture_path # :nodoc:
ActiveRecord.deprecator.warn(<<~WARNING)
TestFixtures#fixture_path is deprecated and will be removed in Rails 7.2. Use #fixture_paths instead.
If multiple fixture paths have been configured with #fixture_paths, then #fixture_path will just return
Expand Down
19 changes: 19 additions & 0 deletions activesupport/lib/active_support/test_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,25 @@ def parallelize_setup(&block)
def parallelize_teardown(&block)
ActiveSupport::Testing::Parallelization.run_cleanup_hook(&block)
end

# :singleton-method: fixture_paths
#
# Returns the ActiveRecord::FixtureSet collection.
#
# In your +test_helper.rb+ you must have <tt>require "rails/test_help"</tt>.

# :singleton-method: fixture_paths=
#
# :call-seq:
# fixture_paths=(fixture_paths)
#
# Sets the given path to the fixture set.
#
# Can also append multiple paths.
#
# ActiveSupport::TestCase.fixture_paths << "component1/test/fixtures"
#
# In your +test_helper.rb+ you must have <tt>require "rails/test_help"</tt>.
end

alias_method :method_name, :name
Expand Down

0 comments on commit c25cc2e

Please sign in to comment.