Ruby on Rails / July 4, 2025 / 3 mins read / By Wagner Matos

Constant Collision in Rails: When Your Concerns Clash with Gems

While working on a Rails app recently, I stumbled across a frustrating bug that only appeared in the test environment. Everything worked perfectly in the development console. Models loaded fine. Associations were intact. My concern methods behaved exactly as expected. But then my test suite started throwing mysterious NoMethodErrors—complaining that an ActiveRecord model was missing associations it clearly had.

Here’s the story—and how I found the unexpected culprit: a name collision with a Ruby gem.

The Setup

In my application, I created a concern named Addressable to encapsulate some reusable address logic:

# app/models/concerns/addressable.rb
module Addressable
  extend ActiveSupport::Concern

  included do
    has_many :addresses, as: :addressable, dependent: :destroy
    accepts_nested_attributes_for :addresses, allow_destroy: true, reject_if: :all_blank
  end

  def full_address
    addresses.last&.to_s || "No address available"
  end
end

Then I included this concern in my Estate model:

class Estate < ApplicationRecord
  include BelongsToOrganisation
  include Addressable
  include ActiveAccountingPeriod

  has_many :blocks
  has_many :properties, through: :blocks
end

Everything worked flawlessly in the Rails console. I could create estates, associate addresses, and call full_address. But in my tests, I started getting this:

NoMethodError: undefined method `addresses' for #<Estate ...>

Debugging the Ghost

At first, I assumed it was a lazy-loading issue in test. Maybe the concern hadn’t loaded yet? I added Rails.application.eager_load! to my test setup. No change. I tried explicitly requiring all concern files. Still broken.

I added this debug line:

puts Estate.ancestors

To my surprise, the Addressable module was nowhere in the ancestor chain—even though I had clearly written and included it.

So what was this Addressable?

The Hidden Culprit: The addressable Gem

After some head-scratching and a puts Addressable in the test environment, I finally saw the issue:

Addressable # => Addressable::URI

Bingo.

Rails (and Ruby in general) had loaded the addressable gem before loading my concern. That gem defines a top-level Addressable module for URI parsing. Because of the name conflict, my local Addressable concern was being silently overshadowed in the test environment—likely due to eager loading or load order quirks.

That’s why the console (where code loads lazily) worked fine, but the test suite (where dependencies load eagerly or in different order) didn’t.

The Fix: Rename Your Concern

Once I renamed my concern to avoid the collision, everything started working again:

# app/models/concerns/has_addresses.rb
module HasAddresses
  extend ActiveSupport::Concern

  included do
    has_many :addresses, as: :addressable
  end
end

And in the model:

class Estate < ApplicationRecord
  include HasAddresses
end

Alternatively, I could’ve namespaced it to avoid polluting the top-level constant space:

# app/models/concerns/concerns/addressable.rb
module Concerns
  module Addressable
    extend ActiveSupport::Concern
    ...
  end
end

And then:

include Concerns::Addressable

Takeaways

  • Avoid using concern names that match top-level gem constants. Even common-sounding names like Addressable, JSON, or URI can create conflicts.
  • Be explicit with module namespaces. It prevents accidental collisions and clarifies intent.
  • Test environment bugs often stem from autoloading differences. Development is lazy. Test is eager. Order matters.
  • Use reflection and debugging tools. Object.const_source_location(:Addressable) and Model.ancestors are your friends.

Final Thoughts

This was a subtle bug that cost me more time than I’d like to admit. But it’s also a great reminder: in Ruby and Rails, naming matters. A lot.

If you ever hit a situation where your code works in development but fails in test, and nothing makes sense—check your constants. You might not be loading what you think you are.

Happy coding!