Making Rails use ActiveRecord for only some requests - mysql

I have a Rails application in which the vast majority of requests do not use ActiveRecord in any way. It would be nice if the rest of the application worked seamlessly when MySQL was unavailable. However, it seems that on each request, ActiveRecord::Base.verify_active_connections! is called. This means that every endpoint breaks, when really just the ones that use ActiveRecord need to break. How can I configure things so that the actions that do not require ActiveRecord will work fine in the absence of MySQL?

Override it!
class ActiveRecord::Base
def self.verify_active_connections!
begin
super
rescue
puts "Do something"
end
end
end
Probably not the best idea to just do a blanket begin/rescue but you get the point. For more information check this question out: "MySQL server has gone away" with Ruby on Rails

Related

Using the rails gem database_cleaner when rSpec testing and using activerecord-sqlserver-adapter

I am using the activerecord-sqlserver-adapter gem to connect to a 2008 SQL Server Database within my rails application. Please note that I do connect to multiple db's throughout my application using 'establish_connection'. I use rSpec to test my application and I want to remove the entries from the DB that rSpec creates. I googled around and found that the database_cleaner gem would be the answer to my problem so I included the Gem and setup my railsappname/spec/spec_helper.rb as so:
require 'database_cleaner'
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
FactoryGirl.reload
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
I also updated the following line to be false
config.use_transactional_fixtures = false
To my rails_helper.rb RSpec.configure block as that is where that line was originally.
I have also tried changing my strategy to :truncation and that has not made a difference. The data is still being inserted in to the DB and not being deleted after the test has completed. Is this a limitation to the activerecord-sqlserver-adapter and are there workarounds for this? Is this issue being caused by the fact I connect to multiple db's within my app? I have googled around for a while and have not seen anyone else experiencing this same issue so any advise is much appreciated!
Thanks for the heads up, but your stack overflow question is really not about SQL Server or the adapter. It is really a by product of how your software is put together. I'm gonna bet it all has something to do with how you establish connections too. Check out this comment on the adapter.
https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/173#issuecomment-4427121
Basically you want to make sure you only have one model that champions a connection so you can manage it. Most gems only know about ActiveRecord::Base. So if you have an app that has many databases, please make sure you do all the things that entails. It is tricky. So much so I even wrote a blog article about it. You should read it :)
http://technology.customink.com/blog/2015/06/22/rails-multi-database-best-practices-roundup/
Lastly... this is purely subjective... but I am a big fan of Rails transactional fixtures and not running your test with an empty database. My advice:
Use Rails defaults.
Layer a small amount of MiniTest on top. Use my minitest-spec-rails gem :)
Use factory girl... but leverage them in a way for dev/test synergies. See https://github.com/metaskills/named_seeds
Again, purely subjective, but I hope that last bit helps. Cheers.

A callback for ActiveRecord database connections?

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.

Using an in-memory database within a gem

I am writing a gem that does some complex parsing/composition of a plist file.
I thought it would make sense to use the ActiveRecord interface for this and build 'structures' as an in-memory database.
The gem works fine on its own. However, I'd like to be able to incorporate it into a Rails project. The problem is that my gem calls establish_conneciton on ActiveRecord::Base which kills any previous connection the Rails app had.
It does seem to be possible because there's a section in the ActiveRecord::Base documentation titled: Connection to multiple databases in different models
This implies you can subclass from ActiveRecord::Base and call establish_connection on that. The problem then is that you can't define your schema because ActiveRecord::Schema.define uses the connection currently set on Base.
I'm thinking that the only way to do this may be to build the tables into the Rails app the includes the gem. I'd rather not go down that route if I can help it though. Any ideas?
You can view the database setup file for my gem here, if I've not made myself clear.
Many thanks
Thanks for the comments. Andrew Marshall: In this case, my tables are temporary and intended for in-memory use only.
I figured out a solution that may be of use to anyone who stumbles upon this:
Switching connection on ActiveRecord::Schema
Thanks again.

Output ActiveRecord MySQL queries to page

New to rails so bear with me :)
How would I go about appending all of the queries executed by ActiveRecord for each page request to the bottom of the page (i.e. application layout)? Coming from CakePHP, this is a useful tool for ensuring the code I'm writing is efficient.
I know I can change the logger via ActiveRecord::Base.logger = Logger.new(STDOUT), for example, but what would I add in to my layout file to dump a list of the queries being executed? Is there a way for me to configure the ActiveRecord logger to a variable, say in my environment.rb file?
Check out the rails footnotes gem - I think it will likely do what you want here, and give you more features as well. I haven't used it as much lately, but I used it extensively in some Rails v2 apps we had, and I just added it to a Rails v3 application to make sure it still worked as expected (and found some slow queries that need correcting as well! )

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.