In tests you can write users(:alice) to look up a fixture record. The same helper is not available in the Rails console, so debugging a fixture by name means looking it up by primary key (or by some unique attribute that you have to remember). A small console-only initializer brings the test-style helpers into the console.
Prerequisite: the fixtures must be loaded
This initializer does not load fixture data. It only looks records up by their fixture-derived ID. If the database is empty, every helper raises ActiveRecord::RecordNotFound. Load the fixtures first:
bin/rails db:fixtures:load
In the test environment the records are loaded automatically by the test runner.
The initializer
# config/initializers/fixture_console_helpers.rb
Rails.application.configure doUntitled note
console do
require 'active_record/fixtures'
fixture_root = Rails.root.join('test/fixtures')
helpers = Module.new do
Dir.glob(fixture_root.join('**/*.yml')).each do |path|
fixture_name = Pathname(path).relative_path_from(fixture_root).sub_ext('').to_s
method_name = fixture_name.tr('/', '_')
model_class =
begin
fixture_name.classify.constantize
rescue NameError
next
end
define_method(method_name) do |*labels|
records = labels.map do |label|
id = ActiveRecord::FixtureSet.identify(
label,
model_class.type_for_attribute(model_class.primary_key).type
)
model_class.unscoped.find(id)
end
labels.one? ? records.first : records
end
end
end
TOPLEVEL_BINDING.receiver.extend(helpers)
end
end
In the console:
$ bin/rails console
>> users(:alice)
=> #<User id: 825285963, name: "Alice", ...>
>> users(:alice, :bob)
=> [#<User id: 825285963, ...>, #<User id: 117902083, ...>]
What the code does
When a Rails console starts, the console block fires once and walks every YAML file under test/fixtures/. For each file it derives a helper name from the path (users.yml becomes users) and maps it back to a model class via classify.constantize . It will also silently skip any files that cannot be resolved.
For each fixture file it then defines a method that takes one or more labels, computes the deterministic record ID with ActiveRecord::FixtureSet.identify (the same call Rails uses during db:fixtures:load), and looks the record up with unscoped.find so default scopes such as multi-tenant filters do not hide it.
The freshly populated module is mixed into the IRB top-level main object via TOPLEVEL_BINDING. It is the same hook Rails uses to expose app, helper, and controller.
Caveats
- Namespaced fixtures need a matching model. A file at
billing/order.ymlresolves toBilling::Order. If your fixture directory layout doesn't match the model namespace,classify.constantizeraises and the helper is silently skipped. - If a top-level method with the same name as a fixture helper already exists in your console environment,
extendoverrides it.