Troubleshooting is often intimidating for people new to code. It’s easy to feel lost and have no idea where to start. To that end, I wanted to share a recent troubleshooting attempt of mine at work.

I am upgrading our gems in our test environment to Ruby 2.3.3, and as part of that, I’ve been working on a particular gem that relies heavily on ActiveRecord. I worked through all the deprecation errors to get our syntax up to current ActiveRecord levels, and then ran bundle exec rake spec as the final step before building the gem.

Except they all failed. Wooooo.

Why did they fail?
I scroll up my list of failures and see a bunch of FactoryGirl::DuplicateDefinitionError: Factory already registered. Most if not all of my tests are failing from this. I do a few searches on this but can’t find anything helpful.

Is this the only failure?
I scroll all the way to the top and see that one test does not fail due to FactoryGirl::DuplicateDefinitionError. The very first test fails due to ActiveRecord::Base.establish_connection(CONNECTION_NAME) ActiveRecord::AdapterNotSpecified: database configuration does not specify adapter.

Ah. This would cause problems on downstream tests, if I can’t even establish the starting connection to the test database. This is could be fueling the FactoryGirl errors. I don’t know anything about FactoryGirl, and the DuplicateDefinitionError sounds like it’s separate from failing to establish a connection at all to the database, but what they hey. Fixing FactoryGirl definitely won’t fix ActiveRecord, and there’s an off-chance fixing ActiveRecord will give me a boost with figuring out FactoryGirl.

What does the internet say?
I grab the failure line, and find a lot of things along the lines of this StackOverflow article. It doesn’t seem to be much help, becase my config.yml file looks good, and I have sqlite3 installed. So what do I do now?

What’s the top line in the stack trace?
That points to my lib/company_name/gem_name.rb file. I go there.

Is the way we’re calling establish_connection different now?
In this file, I see our setup of def establish_connection which includes ActiveRecord::Base.establish_connection(CONNECTION_NAME). OK, cool. This is the exact line from my error message. I’ve found the culprit.

What is wrong with this line?
I assume this is an issue with our syntax again, due to deprecation, and I spend a lot of time searching ActiveRecord docs to try to understand A) what’s happening in general since I don’t fully understand this thing, and B) see if there have been breaking syntax changes in creating connections since the version we used to use and the most current version.

I find nothing.

What else could it be?
The syntax all looks fine from what I’ve learned about ActiveRecord. We’re feeding in options to establish a connection based on the given database. Something must be breaking further up the chain. Back to the stack trace.

Where does the configuration specify an adapter?
Since this question is based off of the literal error message, it’s where I probably should have started anyway. Well, that’s embarrassing. Looking at my stack trace, I see that the arguments being passed into the ActiveRecord::Base.establish_connection(CONNECTION_NAME) come from a integration_spec.rb file. However, the error is in the require statement on line 1, not with any way that file is calling this function specifically. Huh.

What is being required that’s failing?
This file is requiring spec_helper.rb. That file is also listed in my stack trace. I’m getting closer. In spec_helper.rb, I look for the line where it’s calling establish_connection - line 29 - as well as the line listed in the stack trace - line 30.

What argument am I giving this call of establish_connection? That would be a dbconfig variable that I declare a couple of lines up.

OK, so what is that dbconfig variable resolving to?
dbconfig makes use of StandaloneMigrations::Configurator.load_configurations[:test].

Is the syntax right?
I am not familiar with this standalone_migrations gem. A couple minutes of searching assures me the syntax is not deprecated.

I do have the standalone_migrations gem installed that I’m requiring, right?
gem list shows this gem, with the most current version.

What is StandaloneMigrations::Configurator.load_configurations[:test] returning?
I throw in a puts "dbconfig = #{dbconfig}" and re-run bundle exec rake spec. I get dbconfig = in my test output. (As in, my dbonfig variable is empty, nil, nada, no-way.)
I open up an IRB, require 'standalone_migrations', and run StandaloneMigrations::Configurator.load_configurations[:test]. Predictably, I receive nil as the result.
I double check my config.yml file, which houses the settings for my test environment. Everything checks out. Huh.

What’s an obvious thing I can try?
You know, I’ve been reading a lot lately about how you should use ["test"] syntax instead of [:test] because the : syntax is kinda unique to Ruby and would confuse a new person.

What would happen if I change [:test] to ["test"] in my IRB call?
I try it, and get back {"adapter"=>"sqlite3", "database"=>"path/to/db/test.sqlite3", "pool"=>5, "timeout"=>5000}
WOOHOOO Y’ALL.
Time to update my spec_helper.rb.
My elation is short-lived, as I still get the same failure. However, my puts statement is now returning dbconfig = {"adapter"=>"sqlite3", "database"=>"path/to/db/test.sqlite3", "pool"=>5, "timeout"=>5000}, so that’s something.
Huh.
The stack trace is the same. So the error was before that dbconfig line…which makes sense since the dbconfig stuff was on lines 26-29, and my stack trace clearly points to line 30 as the culprit. However, my efforts were not in vain because line 30 uses the variable connection which is set on line 29 like so: connection = Vht::ConfigAdapter.establish_connection(dbconfig).
So I believe I am just a step ahead in my troubleshooting. Now to take a step back for the problem in front of my face.

What does line 30 say?
database_cleaner = DatabaseCleaner[:active_record, {:connection => connection}]

Is this another problem of : syntax versus ""?
To the IRB, Robin!
require 'database_cleaner'
DatabaseCleaner[:active_record, {:connection => connection}]
NameError: undefined local variable or method 'connection' for main:Object
Oh, duhhh. I try again, running the code defining dbconfig so I can feed it into the connection variable definition.
connection = CompanyName::GemName.establish_connection(dbconfig)
NameError: uninitialized constant CompanyName
DUH again. A glance up at all the requires in this spec_helper.rb and -
require 'company_gem_name'
connection = CompanyName::GemName.establish_connection(dbconfig)
ActiveRecord::AdapterNotSpecified: database configuration does not specify adapter
But it does. I is confused.

Why isn’t my sqlite3 adapter coming through?
I double-check my adapter setting to make sure. Yep, it’s right there, in the output of setting my dbconfig variable: "adapter" => "sqlite3".
Options as I see them:

  • sqlite3 isn’t installed
  • something weird with syntax : vs "" making it unable to read the adapter setting that is clearly there

What’s the status of sqlite3?
gem list sqlite3 shows sqlite3 1.3.13 x64-mingw32.
Ugh. I hope this isn’t a DevKit problem. Blahhhhh. I recently learned that on Windows (which I am on), DevKits for different Ruby versions behave differently, and the x64-mingw32 tells me this gem was compiled by DevKit, so maybe I have some funny business going on there.
Some searching turns up that if it couldn’t find sqlite3 at all, I would get an error like sqlite3 is not part of the bundle

And guess where I am. Back to searching for that error phrase. I don’t feel like this time was wasted though, because I’ve learned more about how ActiveRecord works, and I have a more full picture in my mind of how these pieces are working together. I am however, at a bit of a loss.

Ask for help
It’s time.

How I ask for help
I don’t go through all of that above work. I explain where my mind is:

  • I’m getting this error message ActiveRecord::AdapterNotSpecified: database configuration does not specify adapter
  • I am listing an adapter of sqlite3 in my config.yml and it’s being pulled in correctly, as verified by my code runs in IRB
  • sqlite3 is in my Gemfile.lock as well as in my gem list, so I believe it’s there
  • One thing I’m curious about: in my .gemspec file that pulls in dependencies, there are s.add_dependency and s.add_development_dependency. Internet searching shows me these are the two options, and there is no .add_test_dependency option. Are the development_dependency gems (of which sqlite3 is one) being used in my test setup?
  • Halp.

OK, I’m back. I have learned things!
The way this is set up, it is theoretically pointing to a test version of a sqlite3 database. That’s what it’s missing.
Theoretically.
HOWEVER.
Under my db folder, in the same folder as my config.yml no less, I see, plain as day, the test.sqlite3 database. In fact, I earlier created this as part of my db:migrate and db:seed commands. And this matches the path that is spit out when I initialize that dbconfig variable. So that is what I am sending to establish_connection.

So. Why is ActiveRecord not seeing this database?
For the hell of it, since all my configurations have the same setup, and to get ideas out of my head, I’m going to run those IRB commands with “development” instead of “test”. Be back in a sec.


OK same problem. I just had to make sure because I actually created my test.sqlite3 by copy/pasting my development.sqlite3 and I don’t know, maybe the copy/paste didn’t work right. Whatever.
Back to Square 1. Well, I’m at least at Square 2 now. Insofar as I have eliminated options.
BLAH.

I’m going to take a break here. I have some other things I need to do, and then I’m going out for lunch with some co-workers. I’ll be back.




The error messaging in IRB has an ActiveRecord-specific stack trace. The top of that stack points me to line 170 of ActiveRecord’s connection_adapters/connection_specification.rb. Going there, I see this error message is raised unless spec.key?(:adapter), with spec being set as spec = resolve(config).symbolize_keys. config is an argument fed into the function which is also, and totally not confusingly, called spec.
Here is the portion of ActiveRecord’s establish_connection that I am hitting. My error is happening on the last line of this, as resolver.spec takes us to the aforementioned stuff where .symbolize_keys happens and then stuff fails.

def establish_connection(spec = nil)
  raise RuntimeError, "Anonymous class is not allowed." unless name

  spec     ||= DEFAULT_ENV.call.to_sym
  resolver =   ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
  # TODO: uses name on establish_connection, for backwards compatibility
  spec     =   resolver.spec(spec, self == Base ? "primary" : name)

But back to that unless spec.key?(:adapter) line. I do, quite clearly, have a key of "adapter", when I set my dbconfig variable to my test configuration. Let me try manually symbolizing the keys of that output and see if I get back something wonky.
Nope, sure don’t. I get back {:adapter=>"sqlite3", :database=>"path/to/db/development.sqlite3", :pool=>5, :timeout=>5000}. And when I run in IRB spec = dbconfig.symbolize_keys and spec.key?(:adapter) it all checks out.
So WHY IS THIS HAPPENING.
Well. ActiveRecord doesn’t do a strict spec = dbconfig.symbolize_keys. It is actually running spec = resolve(dbconfig).symbolize_keys. Time to dig into this resolve business.


OK back from lunch.

What resource haven’t I used yet?
The Issues on GitHub! I found this issue which linked to this gist which had a comment by this wonderful jehughes which said:

“I’m using Ruby 2.3.1 and found I needed to change the env variable to a symbol when making the connection: ActiveRecord::Base.establish_connection DatabaseTasks.env.to_sym Otherwise I was getting a missing adapter error.”

Ahhhhhh.
After a minor flub with forgetting that parentheses aren’t required in Ruby and that the DatabaseTasks.env.to_sym was an argument and not a separate method, I implemented this lovely fix, which involved changing ActiveRecord::Base.establish_connection(CONNECTION_NAME) to ActiveRecord::Base.establish_connection(CONNECTION_NAME.to_sym).

Tested in IRB. Got back a whole object rather than an error message about missing a database adapter.

Changed my code. Ran bundle exec rake spec.

And look at that! Now I have a whole slew of failing tests! A quick glance through the ~100 failing tests shows lots of syntax deprecation. Here’s hoping my full update of this gem is Ruby 2.3.3 is in sight.

knock on wood

Oh I forgot to mention – the deprecation errors I worked through at the start of this? Yeah those were just from getting the database to seed correctly. Now the real deprecation upgrade work begins.

As a final note, my troubleshooting is still a work-in-progress. I keep reminding myself to check the Issues first! These are at least as helpful as StackOverflow, and rarely show up as well in blanket internet searches, whether using Google or DuckDuckGo or otherwise. CHECK THE ISSUES, SELF. CHECK THE ISSUES.

Final-final note: I just had another problem that I solved in ~5 minutes because I checked the Issues first. See, I do learn!