ActiveRecord MySQL Lost connection to MySQL server during query - mysql

I'm having an issue connecting to an external AWS Aurora MySQL in my Rails app in production.
Here is the setup:
One main PostgreSQL database for the app
One external (AWS Aurora MySQL) database used as a reader for huge datasets
In development, everything works fine, but when I deploy to Heroku, I can only successfully query one table of the external database. When I create another table I get this error message:
ActionView::Template::Error (Mysql2::Error::ConnectionError: Lost connection
to MySQL server during query: SELECT `TMC_Identification`.`direction`,
`TMC_Identification`.`miles`, `TMC_Identification`.`road`,
`TMC_Identification`.`tmc` FROM `TMC_Identification`) :
1: <%= raw(#tmcs.to_json) %>
Rails 5.2
Ruby 2.5.3
Models:
class TmcReading < ApplicationRecord
establish_connection(:tmc_data)
self.table_name = "TMC_Readings"
end
class TmcIdentification < ApplicationRecord
establish_connection(:tmc_data)
self.table_name = "TMC_Identification"
end
database.yml:
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
production:
<<: *default
database: production
username: admin
password: <%= ENV['DATABASE_PASSWORD'] %>
tmc_data:
adapter: mysql2
encoding: utf8
database: tmc_data
username: <%= Rails.application.credentials.tmc_data_db[:username] %>
password: <%= Rails.application.credentials.tmc_data_db[:password] %>
host: tmc-data.cluster-ro-xyz.us-east-1.rds.amazonaws.com
port: 3306
Controller Action
def tmc_identifications
#tmcs = TmcIdentification.all.select(:direction, :miles, :road, :tmc)
end
View
<%= raw(#tmcs.to_json) %>
Everything works fine in development, but not in production. The same database and credentials are used in production for the "tmc_data" connection.
I assume I'm having some thread safety issues, but I'm not sure how to fix that.

The way I solved this problem is the following way:
Models:
class TmcData < ActiveRecord::Base
self.abstract_class = true
establish_connection(:tmc_data)
end
class TmcReading < ApplicationRecord
self.table_name = "TMC_Readings"
end
class TmcIdentification < ApplicationRecord
self.table_name = "TMC_Identification"
end
More details: https://www.thegreatcodeadventure.com/managing-multiple-databases-in-a-single-rails-application/
Also, I stopped connecting to the same secondary database with my development and production environment.

Related

Rails 4.1.1 Postgres app with Mysql Legacy database Import

I've been building a rails app using a postgres database but of course I also have been tasked with importing data from a legacy mysql database.
The way I've been handling this so far:
# config/database.yml
development:
adapter: postgresql
encoding: unicode
database: myapp_development
pool: 10
username: myuser
password:
legacy_development:
adapter: mysql2
encoding: utf8
reconnect: false
database: myapp_legacy
pool: 10
username: myuser
password:
socket: /tmp/mysql.sock
# app/models/legacy.rb
class Legacy < ActiveRecord::Base
self.abstract_class = true
establish_connection "legacy_#{Rails.env}".to_sym
def self.import
self.find_each do |object|
imported_model = object.class.model.new object.attribute_map
object.report_failures unless imported_model.save
end
end
def self.import_all
Rails.application.eager_load!
self.subclasses.each {|subclass| subclass.import }
end
end
# app/models/legacy/chapter.rb
# a bunch of different subclasses like this
class Legacy::Chapter < Legacy
self.table_name = 'chapters'
def self.model
'Chapter'.constantize
end
def attribute_map
{
id: id,
name: name,
body: chapterBody
}
end
end
Then I have a rake task that runs Legacy.import_all. A lot of this was stolen from this post.
There's a few things wrong with this:
The main problem is, when i run Legacy.import_all it makes it through about half of the tables then I get an error like:
NoMethodError: undefined method 'import' for Legacy::SomeSubclass(Table doesn't exist):Class
I think this is because we just have too many connections in the pool. It seems though like it is looking for the SomeSubClass table_name from within the postgres database, but it should be looking on the mysql database.
This is probably because of the methods like:
def self.model
'Chapter'.constantize
end
in the above subclass. I am doing it like that instead of:
def self.model
Chapter
end
because I have a normal model (non-legacy) in my app also called Chapter and I was running into scoping issues there as well.
Anyways this is a huge mess and any thoughts about where I should dig would be greatly appreciated.
Thanks
Can you try prefixing subclass.import with ::
def self.import_all
Rails.application.eager_load!
self.subclasses.each {|subclass| ::subclass.import }
end

Connecting to a separate mysql database in Rails

I am trying to connect to a separate mysql database than what my rails app is on. I am trying to connect to a database of guitar tabs so that users can search for specific songs.
I have my database.yml configured to:
tabs:
adapter: mysql2
encoding: utf8
database: (dbname)
username: (username)
password: (pass)
host: hostname.rds.amazonaws.com
port: 3306
So far I have tab.rb as my model:
class Tab < ActiveRecord::Base
self.abstract_class = true
establish_connection ('tabs')
end
finally, my controller
class TabController < ApplicationController
def listTabs
#tabs = Tabs.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #tabs }
end
end
def showTabs
#tabs = Tabs.find_by_sql "SELECT * FROM gp"
respond_to do |format|
format.html # index.html.erb
format.json { render json: #statuses }
end
end
end
I'm new to rails and I really want to get this to work. If you are able to help me just run the query "SELECT * From gp" and display it in my view, I will love you forever.
Thanks for your help!
in your model the name is Tab and you use in controller Tabs i.e is wrong, please use Tab.all or Tab.find_by_sql

How to make a model point to non-default schema

I've searched all over and I can't find anything related to this.
Basically I have the default schema set to abc
In abc I have some tables, etc ...............
I want to make a model that uses table mobile_activity_logs in schema def
The default rails model looks like this:
class MobileActivityLogs < ActiveRecord::Base
# attr_accessible :title, :body
end
but the query is on abc.mobile_activity_logs and not def.mobile_activity_logs
abc.mobile_activity_logs doesn't exist
In the database.yml file:
tester:
adapter: mysql2
database: def
host:
port:
username:
password:
enable_call: true
flags: CLIENT_MULTI_RESULTS
In the model:
class MobileActivityLogs < ActiveRecord::Base
establish_connection "tester"
self.table_name = "mobile_activity_logs"
end
This is a bit ugly though as it will make a second connection just to access a different schema :/

Rails: specifying a different database in the model

I'm trying to set up Rails (v3.2.2) to use multiple databases. I'm doing this based on this Connecting Rails 3.1 with Multiple Databases.
My model:
class Category < ActiveRecord::Base
establish_connection :category_database
self.primary_key = "cat_id"
validates_presence_of :name, :display_name, :description, :icon, :image, :parent_category_id, :create_time
end
database.yml:
category_database:
adapter: mysql2
encoding: utf8
reconnect: false
database: main_cat
pool: 5
username: root
password: blah
socket: /var/run/mysqld/mysqld.sock
When I run this spec file:
require 'spec_helper'
describe Category do
puts "ENV: #{Rails.env}"
it { should validate_presence_of :name }
it { should validate_presence_of :display_name }
it { should validate_presence_of :description }
it { should validate_presence_of :icon }
it { should validate_presence_of :image }
it { should validate_presence_of :parent_category_id }
it { should validate_presence_of :create_time }
end
like this:
>rspec /path/to/category_spec.rb
I get:
/home/user/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:45:in `resolve_hash_connection': database configuration does not specify adapter (ActiveRecord::AdapterNotSpecified)
I've also tried setting establish_connection like this:
establish_connection(
:adapter => "mysql2",
:encoding => "utf8",
:reconnect => false,
:database => "main_cat",
:pool => 5,
:username => "root",
:password => "blah",
:socket => "/var/run/mysqld/mysqld.sock")
which results in the same exception. (AdapterNotSpecified)
What's strange is that if I abandon establish_connection altogether and apply the exact same connection configuration via the database.yml file like this:
test:
adapter: mysql2
encoding: utf8
reconnect: false
database: main_cat
pool: 5
username: root
password: blah
socket: /var/run/mysqld/mysqld.sock
it works.
It seems that Rails is ignoring establish_connection altogether...am I missing some application-level config setting or something? How do I get Rails to recognize establish_connection so that I can place different models in different databases?
Much appreciated!
So it turns out that Rails requires the presence of a default configuration. In this case, the database.yml file still requires a test database. Otherwise, Rails will throw an exception as it expects to establish some connection before the models are initialized. Once the default configuration is loaded, Rails goes on later to initialize the models and then model-level database configuration can take place via establish_connection.
I hope this helps someone else out there. It took me a considerable amount of time running the debugger through
activerecord-3.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb
to figure this out.
I was experiencing the same error for much the same reason, however I did have a test: configuration in my database.yml; but the problem was in my provisioning of the "establish connection" method within the model definition:
establish_connection 'cm_inv_mgmt_' + Rails.env.downcase
although I provided the sections of database.yml for the production/staging and development environments, I was missing cm_inv_mgmt_test!

Multiple DB connection in rails

I am trying to connect multiple database in ROR application.My database.yml is look like this
in your database.yml file
development:
adapter: mysql
username: root
password:
database: example_development
private:
adapter: mysql
username: root
password:
database: example_private_development
It is possible to connect using establish_connection :private
My doubt is that how use rake db:create.I am not able get solution from google.
Please help me to clear it.
Try
rake db:create:all
And yes, it's possible to have multiple db connections in a Rails application.
This is what I did once, I have created two classes which inherit from ActiveRecord::Base and set the connections inside those classes.
Then I inherited all my models in one of those classes instead of direct ActiveRecord
Below is an example:
database.yml file
#app uses two database
#1 - test1
#2 - test2
test1:
adapter: mysql
encoding: utf8
database: test1
username: root
password: xxx
host: localhost
test2:
adapter: mysql
encoding: utf8
database: test2
username: root
password: xxx
host: localhost
Then I have two models for both test1 and test2 databases:
class Test1Base < ActiveRecord::Base
self.abstract_class = true
establish_connection("test1")
end
class Test2Base < ActiveRecord::Base
# No corresponding table in the DB.
self.abstract_class = true
establish_connection("test2")
end
Then I inherit my models according to database:
class School < Test1Base
#code
end
class Student < Test2Base
#code
end
Thanks for reply.
we can migrate a model for particular DB, for example
db:migrate RAILS_ENV="portal_development"'.
And more change for establishing connection with DB.check the corrected below
class Test1Base < ActiveRecord::Base
self.abstract_class = true
establish_connection :development
end
class Test2Base < ActiveRecord::Base
# No corresponding table in the DB.
self.abstract_class = true
establish_connection :portal_development
end
Thanks sameera for your valuable reply.
cheers
Shamith c
Possibly use active_delegate?
http://railslodge.com/plugins/595-active-delegate