A callback for ActiveRecord database connections? - mysql

Is there any way to hook into ActiveRecord connection creation? I want to run some code whenever a connection has just been created.
I feel like it might be a way to set a MySQL variable on the connection, since "variables" in database.yml doesn't seem to work for me. (How to turn off MySQL strict mode in Rails)

The ConnectionAdapter defines two callbacks :checkout (connect) and :checkin (disconnect). You can use it for specific adapter as
ActiveRecord::ConnectionAdapters::MysqlAdapter.set_callback :checkout, :after do
raw_connection.set_your_variables ...
end
Or you can use ActiveRecord::Base.connection.class for whatever adapter is currently declared in database.yml

Also, if you need to configure your model after connection has been made and column information was retrieved, you can redefine load_schema! class method in model.
See: https://github.com/rails/rails/pull/31681#issuecomment-357113030

Just to add to the accepted solution, if you need to fire a database query from within the callback, you can do so in the following way:
ActiveRecord::ConnectionAdapters::AbstractAdapter.set_callback :checkout, :before, ->(conn) {
res = conn.execute('SELECT COUNT(*) from table_name')
puts "res is #{res.each { |tuple| puts tuple.inspect}}"
}
Note: since callback is defined on ActiveRecord::ConnectionAdapters::AbstractAdapter, this should be executed before checking out connection for ANY database type
As #Envek pointed out in comment to the accepted answer, you should not really use ActiveRecord models since you risk running into endless recursion. Also (also noted by #Envek) keep in mind that the callback will be fired on each connection checkout with pooled connections, not just once.
Finally, the chances are, you want to use this from Rails. If so, you can place this code in a file under config/initializers folder. Then it would be run on application startup. Useful for cases where you want to add logic to how database connection is established, especially if precise action depends on results of a specific query.

Related

how to check where mysql dababase exists from rails env?

My app, must work with multiple db's for many reasons. I work on custom model for db connection establishing, where I need to establish new db connection, based on arg's, .
So, for example, before establishing new connection using:
ActiveRecord::Base.establish_connection new_config
Where new_config is customized clone, of database.yml
I want to check whether new DB exists before any db connections establishing. So I need a function db_exists? db_name that will return boolean value, based on whether db exists or not.
It seems a bit illogical to be able to check whether or not a database exists without a connection to that database, but that may just be me.
I recommend you consider using a rescue block to attempt the connection and then handle the appropriate exceptions.
The exceptions you can receive from that attempt are discussed here.
Just ran across a very good discussion on using rescue here.
We use Rails apps to manage databases themselves, so have to do stuff like this all the time. It's perfectly reasonable to want to know about databases besides the current Rails data store. It's a lot like checking for the existence of a file that's not part of the current Rails app.
Here's a solution that may be useful in certain situations (this for MySQL):
def db_exists?(db_name)
ActiveRecord::Base.connection.execute("SHOW DATABASES LIKE '#{db_name}'").size > 0
end
You have to have SOME database connection but it certainly does not have to be for the database you are querying for existence. (Note this implementation is NOT protected against sql injection... it requires you only pass in clean, valid db_name.)

Django multiple databases - can't connect to mysql server fallback to sqlite

I have a django applicaiton with multiple databases. The default database is on the local machine. There is also a remote mysql database which is used for some write operations, but it is not always up. When the server is down, mysqldb raises an OperationalError.
I would like have a local sqlite database called 'fallback' which would accept the data if the mysql server is down. I realize that this involves at try/except clause in django.db.mysql.base, but I am not quite sure where to go from there. Has anyone tried something similar? Do you have suggestions on a better way to handle this?
You could probably use Database Routers in combination with a custom base Model class that overrides the save method. Wrap it in a try..catch, and if the OperationalError occurs, provide some hints so your database router can determine if the fallback needs to be used.
I think this will be the cleanest way, rather than modifying the django code itself.

Transaction in Enterprise library

How to handle transaction within a scope using Enterprise library. I've 3 stored procedures, which I need to execute in a single scope. I dont want to use System.Transaction name space
You can call the BeginTransaction method on a connection object to get a DbTransaction object. Then use the Entlib Database object's overloads that take a DbTransaction. However, it's a giant pain to manage. You'll need to create and close least one connection manually rather than relying on Entlib to do the right thing, and you'll have to pass the DbTransaction object around to everything that needs it.
TransactionScope really is the right answer here. If you've got some blocking scenario that really prevents you from using it that isn't some brain-dead corporate policy, I'd love to know what it is.

Can I reuse the connection from DataContext in Linq to Sql?

DataContext has Connection property of type DbConnection and I was wondering if I could re-use it. I've tried to use it creating a command using CreateCommand and using a reader off of it but I've gotten errors saying there is a pending transaction or something similar.
Basically I'm trying to find out if there is a best practice or guidance on re-using that connection object.
The connection string itself doesn't really help since I can't create a new connection object with the abstract type and I don't want the code to know the specific provider type either.
One alternative approach I'm thinking of doing is having my DataContext derived type to have members that provide a factory method to create a new connection using the same connection information.
FYI, this inquiry stems from the need to invoke an ad-hoc stored procedure through DataContext, not the design-time ExecuteMethodCall variety. I didn't know about ExecuteQuery and for now that suffices. But for other situations where ExecuteQuery is inadequate, I'd need the low-level data access using connection/command etc.
Why not turn it around, and instead supply connections to the datacontext by using the constructor that takes a connection as a parameter? That way you can control when connections are created and disposed, opened and closed, and can reuse them for other purposes without having to worry about the internal behavior of the L2S datacontext...
I can't say definitely, but a connection is a connection. Until it's been closed (or returned to the connection pool), it should be viable to use, whether via LINQ or other means.

Sharing a database connection with included classes in a Sinatra application

I'm converting a part of a rails application to its own sinatra application. It has some beefy work to do and rather than have a million helps in app.rb, I've separated some of it out into classes. Without access to rails I'm rewriting finder several methods and needing access to the database inside of my class. What's the best way to share a database connection between your application and a class? Or would you recommend pushing all database work into its own class and only having the connection established there?
Here is what I have in in app.rb
require 'lib/myclass'
configure :production do
MysqlDB = Sequel.connect('mysql://user:password#host:port/db_name')
end
I want to access it in lib/myclass.rb
class Myclass
def self.find_by_domain_and_stub(domain, stub)
# want to do a query here
end
end
I've tried several things but nothing that seems to work well enough to even include as an example.
Assuming you're not doing any threading, just set up the connection as a global var.
require 'lib/myclass'
before do
$MysqlDB = Sequel.connect('mysql://user:password#host:port/db_name')
end
class Myclass
def self.find_by_domain_and_stub(domain, stub)
# use $MysqlDB here
end
end
Might be wise to check the connection timeout settings, or explicitly disconnect from the server. If you're handling a lot of requests, you could run out of connections before they time out.
Tim Rosenblatt's answer will reconnect on every request. It's better to do the following in your Sinatra app:
require 'sequel'
DB = Sequel.connect('mysql://user:password#host:port/db_name')
require 'lib/myclass'
It's better to use a constant than a global variable in this case.