Isnor Creative
Isnor Creative Blog
Ruby, Ruby on Rails, Ember, Elm, Phoenix, Elixir, React, Vue

Aug 29, 2015

Ruby on Rails and Phoenix Ecto Sharing A Database

I found a curious problem recently where I built what for the sake of argument we’ll call an “admin control panel” application in Ruby on Rails. The application was originally designed as an internal tool for a company. Eventually the company decided that they wanted to incorporate some of the existing data, as well as data from additional website-specific tables, into a new website.

I decided to build the website with Ember.js on top of a Phoenix API. The site accesses the same database, in otherwords, as the internal Rails application. The Phoenix API is a GET-only API, existing solely to provide content for the site.

That all worked splendidly until I started building building out the suite of tests. I ran rake RAILSENV=test db:drop, rake RAILSENV=test db:create and rake RAILSENV=test db:migrate on my Rails application’s test database. At this point I believe that a recent version of Rails may have changed the design of the schemamigrations table? Because I started getting the following error when I ran mix test:

** (ArgumentError) cannot load `"20110909131101"` as type :integer
    (ecto) lib/ecto/repo/queryable.ex:132: Ecto.Repo.Queryable.load!/3
    (ecto) lib/ecto/adapters/sql.ex:499: anonymous fn/3 in Ecto.Adapters.SQL.process_row/3
    (elixir) lib/enum.ex:1036: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    (ecto) lib/ecto/adapters/sql.ex:497: Ecto.Adapters.SQL.process_row/3
    (elixir) lib/enum.ex:977: anonymous fn/3 in Enum.map/2
    (elixir) lib/enum.ex:1261: Enum."-reduce/3-lists^foldl/2-0-"/3
    (elixir) lib/enum.ex:977: Enum.map/2
    (ecto) lib/ecto/adapters/sql.ex:267: Ecto.Adapters.SQL.decode/2

As it turns out, Ecto and ActiveRecord use the same table name for tracking migrations: schema_migrations, but Ecto expects the version column to be an integer rather than the string that ActiveRecord prefers.

I did some digging and it seems that customizing this in Ecto and ActiveRecord is not currently an option, but the solution that I landed at was changing the table name that Rails uses in config/initializers/activerecordextensions.rb:

class ActiveRecord::SchemaMigration
  
  def self.table_name
    "schema_versions"
  end
  
end

This does necessitate manually renaming the table in test, development and production databases.

I first wrote a rake task to rename the table in lib/schemamigrationsrename.rake:

namespace :schema_migrations_rename do

  desc "do"
  task :do => :environment do
    puts "Renaming schema_migrations table to schema_versions"
    ActiveRecord::Base.connection.execute('ALTER TABLE schema_migrations RENAME TO schema_versions;')
    puts "Job complete..."
  end 
    
end

and ran it with:

    $ rake RAILS_ENV=production schema_migrations_rename:do

I ran into a spot of trouble when I hit production with capistrano… Something funky happened with my capistrano deploys, which does automated migrations. It must have responded to the changed ActiveRecord::SchemaMigration table_name declaration by adding a new table while automatically running migrations as part of the deploy process. So I then ssh’d to the machine and added the records from the schema migrations table to the schema versions table.

$ bundle exec rails console
    a.each do |item| 
      ActiveRecord::Base.connection..connection.execute("INSERT INTO schema_versions (version) VALUES ('#{item['version']}')") 
    end

Deploys ran smoothly after that.


I am available for Rails and Elixir/Phoenix consulting work – get in touch to learn more.

Gordon B. Isnor

Gordon B. Isnor writes about Ruby on Rails, Ember.js, Elm, Elixir, Phoenix, React, Vue and the web.
If you enjoyed this article, you may be interested in the occasional newsletter.

I am now available for project work. I have availability to build greenfield sites and applications, to maintain and update/upgrade existing applications, team augmentation. I offer website/web application assessment packages that can help with SEO/security/performance/accessibility and best practices. Let’s talk

comments powered by Disqus