Reputation: 43
What is the best way to see if their Active Record associations are no longer being used? How can I write a rspec test to see if the association is no longer being used?
I have to refactor someone else's (who is no longer a part of the project) Rails model. Currently, I am using atom to see if the associations are being called elsewhere in the repository, but I know this isn't the best way to do it. I want to build unit tests for the model, but am not completely sure on how to approach this for associations. Currently, I am using shoulda matchers and factory_girl_rails.
Upvotes: 0
Views: 1715
Reputation: 6628
I think this is the problem as old as the software design itself.
It's a problem in dynamic languages like ruby. There are few ways to address that.
Usually, it's difficult to have the 100% coverage, and this solution might not be readily available to you
Like point 1, but manual. Very difficult in bigger systems, and usually you don't have every feature documented.
For associations this may be sth like:
has_namy :foos
def foos
log 'foos is used!'
super
end
But as @chumakoff said here https://stackoverflow.com/a/51982936/299774 the association may be used in few more places. So you'd need to make some investigation to find all the places to hook your logging into.
This solution also has a drawback: how long should you wait until you declare the association unused? Should you wait half a year? What if nobody used it for that long, but there's a feature used once a year, and it got broken?
It depends on the size of the app and criticality etc. Sometimes you can risk it, sometimes you decide to live with some not used code. Or you get more creative like in here Find unused code in a Rails app.
Or you could disable this association for a fraction of users and watch for exceptions coming to wherever you aggregate logs/exceptions.
Maybe you should check the DB if there's anything in the database? If not - can you find a migration that removed all the stuff from there? Can you contact the author?
Upvotes: 0
Reputation: 7024
There are at least two ways the association might be used:
Explicitly - calling on an object.
object.association_name
In this case it is easy to track:
expect_any_instance_of(Model).to_not receive(:association_name)
Another question is where to place this expectation in your test structure.
Implicitly - in complex queries or for associated data preloading.
Model.all.joins(:association_name)
Model.all.includes(:association_name)
In this case it is very hard to track.
I suggest another approach:
Do not track the association usage, instead check if tests pass when the association is removed. You can safely remove the association for the test environment.
For example, you can replace this:
has_many :association_name
with this:
unless Rails.env.test?
has_many :association_name
end
This will not break anything and will raise an error only when running tests and only if the association is being used somewhere.
Upvotes: 1
Reputation: 559
Rspec uses reflect_on_association
for this purpose. An example would be
it 'has many associations' do
assc = Model.reflect_on_association(:other_model)
expect(assc.macro).to eq :has_many
end
Upvotes: 0