The other day, I found myself having to change configuration for some associations. Not wanting to break things, I decided to write some tests to explicitly describe how things are hooked up. While doing this, I decided to try my hand at writing a simple DSL to reduce boilerplate in my tests.
Simply extend AssociationTest
in your test class (which must be a child of ActiveSupport::TestCase
), and use the DSL.
model SomeModel do
primary_key :id
belongs_to :other_model, primary_key: :id, foreign_key: :other_model_id
end
effectively generates
test 'SomeModel uses id as primary_key' do
assert_equal 'id', primary_key.to_s
end
test 'SomeModel belongs_to other_model using id as primary_key' do
assert_equal 'id', SomeModel.reflect_on_association(:other_model).join_primary_key.to_s
end
test 'SomeModel belongs_to other_model using id as foreign_key' do
assert_equal 'id', SomeModel.reflect_on_association(:other_model).join_foreign_key.to_s
end
test 'SomeModel.joins(:other_model) works' do
SomeModel.joins(:other_model).load
end
ruby demo.rb --verbose
This will install the relevant gems using bundler/inline
, as well as setup an in-memory database. If the gem installation fails, ensure you are not using the system Ruby, and have permissions to install gems.
You can increase logging by toggling comments on the following lines:
ui: Bundler::UI::Silent.new,
insetup.rb
# ActiveRecord::Base.logger = Logger.new(STDOUT)
indatabase.rb
For simplicity, this only implements the belongs_to
and has_many
associations. Additionally, the various *_key
methods on AssociationReflection
are super confusing, so this uses join_primary_key
and join_foreign_key
. It should be noted that these that these are dependent on the direction the join is going. While the names match for belongs_to
associations, for has_many
we must invert the names as we are joining in the opposite direction and foreign
in this context refers to the column in the other table.