Allow specify fixtures to be ignored

Allow specifying what fixtures can be ignored by setting
`ignore` in fixtures YAML file:

    # users.yml
    _fixture:
      ignore:
        - base

    base: &base
      admin: false
      introduction: "This is a default description"

    admin:
      <<: *base
      admin: true

    visitor:
      <<: *base

In the above example, "base" fixture will be ignored when creating
users fixture. This is helpful when you want to inherit attributes
and it makes your fixtures more "DRY".
This commit is contained in:
Tongfei Gao 2019-05-18 20:58:22 +08:00
parent d1ffe59ab5
commit c09a4fd23d
6 changed files with 111 additions and 5 deletions

View File

@ -1,3 +1,7 @@
* Allow specifying fixtures to be ignored by setting `ignore` in YAML file's '_fixture' section.
*Tongfei Gao*
* Make the DATABASE_URL env variable only affect the primary connection. Add new env variables for multiple databases.
*John Crepezzi*, *Eileen Uchitelle*

View File

@ -29,6 +29,10 @@ module ActiveRecord
config_row["model_class"]
end
def ignored_fixtures
config_row["ignore"]
end
private
def rows
@rows ||= raw_rows.reject { |fixture_name, _| fixture_name == "_fixture" }
@ -40,7 +44,7 @@ module ActiveRecord
if row
row.last
else
{ 'model_class': nil }
{ 'model_class': nil, 'ignore': nil }
end
end
end

View File

@ -420,6 +420,29 @@ module ActiveRecord
#
# Any fixture labeled "DEFAULTS" is safely ignored.
#
# Besides using "DEFAULTS", you can also specify what fixtures will
# be ignored by setting "ignore" in "_fixture" section.
#
# # users.yml
# _fixture:
# ignore:
# - base
# # or use "ignore: base" when there is only one fixture needs to be ignored.
#
# base: &base
# admin: false
# introduction: "This is a default description"
#
# admin:
# <<: *base
# admin: true
#
# visitor:
# <<: *base
#
# In the above example, 'base' will be ignored when creating fixtures.
# This can be used for common attributes inheriting.
#
# == Configure the fixture model class
#
# It's possible to set the fixture's model class directly in the YAML file.
@ -614,7 +637,7 @@ module ActiveRecord
end
end
attr_reader :table_name, :name, :fixtures, :model_class, :config
attr_reader :table_name, :name, :fixtures, :model_class, :ignored_fixtures, :config
def initialize(_, name, class_name, path, config = ActiveRecord::Base)
@name = name
@ -647,8 +670,8 @@ module ActiveRecord
# Returns a hash of rows to be inserted. The key is the table, the value is
# a list of rows to insert to that table.
def table_rows
# allow a standard key to be used for doing defaults in YAML
fixtures.delete("DEFAULTS")
# allow specifying fixtures to be ignored by setting `ignore` in `_fixture` section
fixtures.except!(*ignored_fixtures)
TableRows.new(
table_name,
@ -667,6 +690,21 @@ module ActiveRecord
end
end
def ignored_fixtures=(base)
@ignored_fixtures =
case base
when Array
base
when String
[base]
else
[]
end
@ignored_fixtures << "DEFAULTS" unless @ignored_fixtures.include?("DEFAULTS")
@ignored_fixtures.compact
end
# Loads the fixtures from the YAML file at +path+.
# If the file sets the +model_class+ and current instance value is not set,
# it uses the file value.
@ -678,6 +716,7 @@ module ActiveRecord
yaml_files.each_with_object({}) do |file, fixtures|
FixtureSet::File.open(file) do |fh|
self.model_class ||= fh.model_class if fh.model_class
self.ignored_fixtures ||= fh.ignored_fixtures
fh.each do |fixture_name, row|
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
end

View File

@ -1279,6 +1279,33 @@ class CustomNameForFixtureOrModelTest < ActiveRecord::TestCase
end
end
class IgnoreFixturesTest < ActiveRecord::TestCase
fixtures :other_books, :parrots
test "ignores books fixtures" do
assert_raise(StandardError) { other_books(:published) }
assert_raise(StandardError) { other_books(:published_paperback) }
assert_raise(StandardError) { other_books(:published_ebook) }
assert_equal 2, Book.count
assert_equal "Agile Web Development with Rails", other_books(:awdr).name
assert_equal "published", other_books(:awdr).status
assert_equal "paperback", other_books(:awdr).format
assert_equal "english", other_books(:awdr).language
assert_equal "Ruby for Rails", other_books(:rfr).name
assert_equal "ebook", other_books(:rfr).format
assert_equal "published", other_books(:rfr).status
end
test "ignores parrots fixtures" do
assert_raise(StandardError) { parrots(:DEFAULT) }
assert_raise(StandardError) { parrots(:DEAD_PARROT) }
assert_equal "DeadParrot", parrots(:polly).parrot_sti_class
end
end
class FixturesWithDefaultScopeTest < ActiveRecord::TestCase
fixtures :bulbs

View File

@ -0,0 +1,26 @@
_fixture:
model_class: Book
ignore:
- PUBLISHED
- PUBLISHED_PAPERBACK
- PUBLISHED_EBOOK
PUBLISHED: &PUBLISHED
status: :published
PUBLISHED_PAPERBACK: &PUBLISHED_PAPERBACK
<<: *PUBLISHED
format: "paperback"
language: :english
PUBLISHED_EBOOK: &PUBLISHED_EBOOK
<<: *PUBLISHED
format: "ebook"
awdr:
<<: *PUBLISHED_PAPERBACK
name: "Agile Web Development with Rails"
rfr:
<<: *PUBLISHED_EBOOK
name: "Ruby for Rails"

View File

@ -1,3 +1,9 @@
_fixture:
ignore: DEAD_PARROT
DEAD_PARROT: &DEAD_PARROT
parrot_sti_class: DeadParrot
george:
name: "Curious George"
treasures: diamond, sapphire
@ -17,7 +23,7 @@ polly:
name: $LABEL
killer: blackbeard
treasures: sapphire, ruby
parrot_sti_class: DeadParrot
<<: *DEAD_PARROT
DEFAULTS: &DEFAULTS
treasures: sapphire, ruby