diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cd53bd3..7ee5e76 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,7 +23,6 @@ jobs: - rails: "7.2" ruby: "3.1" env: - RAILS_ENV: test RAILS_VERSION: ${{ matrix.rails }} name: ${{ format('rails-{0} ruby-{1}', matrix.rails, matrix.ruby) }} @@ -39,6 +38,8 @@ jobs: ruby-version: ${{ matrix.ruby }} bundler-cache: true + - run: bin/rails db:prepare + - name: Parallel Tests run: bin/rails test diff --git a/README.md b/README.md index 454c3cb..74e10e7 100644 --- a/README.md +++ b/README.md @@ -567,7 +567,44 @@ You can convert your Rails fixtures to Oaken's seeds by running: bin/rails generate oaken:convert:fixtures ``` -This will convert anything in test/fixtures to db/seeds. E.g. `test/fixtures/users.yml` becomes `db/seeds/users.rb` and so on. +This will convert anything in test/fixtures to db/seeds. E.g. `test/fixtures/users.yml` becomes `db/seeds/test/users.rb` and so on. + +#### Accessing Oaken seeds from fixtures + +Call `grant_fixture_access` to make Oaken seeds accessible from fixtures: + +```ruby +# db/seeds/test/setup.rb +grant_fixture_access accounts, users +``` + +> [!TIP] +> Since fixtures are a test environment thing, place this in the test-environment dedicated setup in `db/seeds/test/setup.rb`. + +```ruby +# db/seeds/test/accounts.rb +accounts.create :kaspers_donuts, name: "Kasper's Donuts" +accounts.create name: "Demo" # Inaccessible! Pass a label ala `:kaspers_donuts` above to access this record from fixtures. + +# You can also use `accounts.label` to expose records in fixtures. +accounts.label demo: Account.find_by!(name: "Demo") +``` + +Now you can access the created record from fixtures: + +```yaml +# test/fixtures/menus.yml +basic_kasper_menu: + name: "Kasper's Basic Menu" + account: kaspers_donuts + +basic_demo_menu: + name: "Demo's Basic Menu" + account: demo +``` + +> [!WARNING] +> Fixtures truncate data per table before inserting any anything. This means if you have say `test/fixtures/menus.yml`, you can't have any menus in Oaken seeds. So you have to port by file and then every fixture in a file. So convert every fixture in e.g. `test/fixtures/menus.yml` at once. #### Disable fixtures diff --git a/lib/oaken/seeds.rb b/lib/oaken/seeds.rb index 068c1a7..e428fab 100644 --- a/lib/oaken/seeds.rb +++ b/lib/oaken/seeds.rb @@ -48,4 +48,29 @@ def self.respond_to_missing?(meth, ...) = loader.locate(meth) || super # end # end def self.section(*, **) = block_given? && yield + + # Make any labelled records accessible in Rails' fixtures. Useful when porting from fixtures to Oaken. + # + # grant_fixture_access accounts + # + # # Now passing the label `:kaspers_donuts` here makes this record accessible: + # accounts.create :kaspers_donuts, name: "Kasper's Donuts" + # + # # test/fixtures/menus.yml + # basic: + # name: "Basic Menu" + # account: kaspers_donuts # We're accessing the named record by the label here. + def self.grant_fixture_access(*registers) + registers.each { _1.extend FixtureAccess } + end + + module FixtureAccess + def create(label = nil, id: identify(label), **) = super + def upsert(label = nil, id: identify(label), **) = super + + private + def identify(label) + ActiveRecord::FixtureSet.identify(label) if label + end + end end diff --git a/test/dummy/app/models/account/fixture_access.rb b/test/dummy/app/models/account/fixture_access.rb new file mode 100644 index 0000000..9afb249 --- /dev/null +++ b/test/dummy/app/models/account/fixture_access.rb @@ -0,0 +1,3 @@ +class Account::FixtureAccess < ApplicationRecord + belongs_to :account +end diff --git a/test/dummy/db/migrate/20251102174456_create_account_fixture_accesses.rb b/test/dummy/db/migrate/20251102174456_create_account_fixture_accesses.rb new file mode 100644 index 0000000..cdac0f5 --- /dev/null +++ b/test/dummy/db/migrate/20251102174456_create_account_fixture_accesses.rb @@ -0,0 +1,10 @@ +class CreateAccountFixtureAccesses < ActiveRecord::Migration[8.0] + def change + create_table :account_fixture_accesses do |t| + t.references :account, null: false, index: true + t.string :name + + t.timestamps + end + end +end diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb index 01cf1ec..6017143 100644 --- a/test/dummy/db/schema.rb +++ b/test/dummy/db/schema.rb @@ -10,7 +10,15 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2025_10_24_125945) do +ActiveRecord::Schema[8.0].define(version: 2025_11_02_174456) do + create_table "account_fixture_accesses", force: :cascade do |t| + t.integer "account_id", null: false + t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["account_id"], name: "index_account_fixture_accesses_on_account_id" + end + create_table "accounts", id: :string, default: -> { "ULID()" }, force: :cascade do |t| t.string "name" t.datetime "created_at", null: false diff --git a/test/dummy/db/seeds/test/setup.rb b/test/dummy/db/seeds/test/setup.rb new file mode 100644 index 0000000..fc101e0 --- /dev/null +++ b/test/dummy/db/seeds/test/setup.rb @@ -0,0 +1 @@ +grant_fixture_access accounts diff --git a/test/dummy/test/fixtures/account/fixture_accesses.yml b/test/dummy/test/fixtures/account/fixture_accesses.yml new file mode 100644 index 0000000..edcf8ac --- /dev/null +++ b/test/dummy/test/fixtures/account/fixture_accesses.yml @@ -0,0 +1,3 @@ +basic: + name: "Basic Access" + account: kaspers_donuts diff --git a/test/dummy/test/models/oaken_test.rb b/test/dummy/test/models/oaken_test.rb index 570e8f0..2be780a 100644 --- a/test/dummy/test/models/oaken_test.rb +++ b/test/dummy/test/models/oaken_test.rb @@ -23,6 +23,11 @@ class OakenTest < ActiveSupport::TestCase assert_equal [users.kasper, users.coworker], accounts.kaspers_donuts.users end + test "accessing fixture from within rails fixtures" do + assert_equal 1, Account::FixtureAccess.count + assert_equal accounts.kaspers_donuts, Account::FixtureAccess.first.account + end + test "accessing fixture from test env" do assert plans.test_premium end diff --git a/test/dummy/test/test_helper.rb b/test/dummy/test/test_helper.rb index a1e3715..393d0a2 100644 --- a/test/dummy/test/test_helper.rb +++ b/test/dummy/test/test_helper.rb @@ -8,4 +8,5 @@ class ActiveSupport::TestCase parallelize workers: :number_of_processors, threshold: ENV.fetch("PARALLEL_TEST_THRESHOLD", 5).to_i include Oaken.test_setup + fixtures "account/fixture_accesses" end