Preventing an Instance Method from Printing to Console - ruby

I am writing a simple Ruby script that utilizes the mysql2 gem.
In order to properly terminate a connection with the database and avoid the Too many connections error, I store my connection into the variable mysql like so:
mysql = Mysql2::Client.new(:host => hst, :username => usr, :password => pass, :database => db, :connect_timeout => 30)
and then I close the connection:
mysql.close
When this occurs, I get:
closed MySQL connection
in the console.
How can I implement the Instance Method #close found here without closed MySQL connection showing up in the terminal?

you can do this:
def silence_stdout
$stdout = File.new( '/dev/null', 'w' )
yield
ensure
$stdout = STDOUT
end
and do the close with that method
silence_stdout{mysql.close}

Related

Net::SSH gem non_interactive invalid option?

I have Ruby code like so:
def make_ssh user, pass
begin
Net::SSH.start(#host, user, :password => pass, :non_interactive => true) do |session|
#ssh = session
puts #ssh
end
rescue Exception => e
puts e
end
end
In the Net::SSH library source/repo, the :non_interactive command is supposed to negate the password prompt (and I'm assuming use the key/value :password => pass for authentication), but everytime I try to run my code, I am getting an "invalid option" error.
I have tried this with and without the ssh block, and also as
Net::SSH.start(#host, user, {:password => pass, :non_interactive => true})
but nothing seems to work. What am I doing wrong here?
I got the same eror as yours. This option is added in net-ssh 2.10.0. You are probably using the lower version.

Creating a variable per instance, rather than per request, with Sinatra modular style

I have a Sinatra app, written in modular style, running on Heroku. It uses Redis and I have a limited number (10) of Redis connections. I found that it would often throw errors complaining that it had run out of Redis connections. So I started using connection_pool in the hope that would fix things; a single pool of Redis connections and the app would choose one of those each time, rather than try to create a new connection on each request.
But I'm still getting the same issue. I can do loads of Redis queries on a single query without complaints. But if I reload a single test page, which just does some Redis queries, several times in fairly quick succession, I get the "Redis::CommandError - ERR max number of clients reached" error again.
So I'm assuming, maybe, it's creating a new instance of connection_pool on each request... I don't know. But it's not "pooling" as I would expect it to.
I have this kind of thing:
# myapp.rb
$LOAD_PATH.unshift(File.dirname(__FILE__))
$stdout.sync = true
require 'thin'
require 'myapp/frontend'
MyApp::Frontend.run!
And the Sinatra app:
# myapp/frontend.rb
require 'sinatra/base'
require 'redis'
require 'connection_pool'
require 'uuid'
module MyApp
class Frontend < Sinatra::Base
helpers do
def redis_pool
#redis_pool ||= ConnectionPool.new(:size => 8, :timeout => 5) do
redis_uri = URI.parse(ENV['REDISCLOUD_URL'])
client = ::Redis.new(:host => redis_uri.host,
:port => redis_uri.port,
:password => redis_uri.password)
end
end
end
get '/tester/'
redis_pool.with do |r|
id = UUID.generate
r.hset(:user, id, "Some data")
r.hget(:user, id)
r.hdel(:user, id)
end
p "DONE"
end
end
end
The Procfile looks like:
web: ruby myapp.rb
Any ideas? The current site is pretty low traffic, so this should be possible.
A new instance of #redis_pool is created every time a get request for /tester/ is processed because the helper method redis_pool is called every time.
You can use sinatra's settings helper to initialize a redis connection only once:
config do
redis_uri = URI.parse(ENV['REDISCLOUD_URL'])
set :redis, Redis.new(:host => redis_uri.host,
:port => redis_uri.port,
:password => redis_uri.password)
end
Now the each instance of the app has one redis connection that persists for all requests. Access the setting like so
get '/tester/'
id = UUID.generate
settings.redis.hset(:user, id, "some data")
settings.redis.hget(:user, id)
settings.redis.hdel(:user, id)
p "DONE"
end

EM::Synchrony.defer with fiber aware database call causes FiberError exception

I'm trying to use EM-Synchrony for concurrency in an application and have come across an issue with my use of deferred code and Fibers.
Any calls to the database within either EM.defer or EM::Synchrony.defer results in the application crashing with the error can't yield from root fiber
Below is a very trimmed down runnable example of what I'm trying to accomplish. The first print works and displays [:first, 1] but the second is where I crash with the error mentioned above.
require 'mysql2'
require 'em-synchrony/activerecord'
ActiveRecord::Base.establish_connection(
:adapter => 'em_mysql2',
:username => 'user',
:password => 'pass',
:host => 'localhost',
:database => 'app_dev',
:pool => 60
)
class User < ActiveRecord::Base; end
EM.synchrony do
p [:first, User.all.count]
EM::Synchrony.defer do
p [:second, User.all.count]
end
end
My first thought was perhaps the Fiber.current and Fiber.yield within EM::Synchrony.defer meant I could fix the problem with an extra Fiber.new call
EM::Synchrony.defer do
Fiber.new do
p [:second, User.all.count]
end.resume
end
This fails to run as well but this time I get the error fiber called across threads.

ruby active_record connection within a class

My problem is that I want to put my connection and SQL statements in site methods in my class, but when I put it in separate methods and call the methods from elsewhere it won't connect to my MySQL database. My code:
require 'active_record'
class Databaseoperation < ActiveRecord::Base
def initialize
$mysqlinfo = Hash[*File.read('/home/me/properties/mysql.property').split(/=|\n/)]
end
def mysqlConnect
self.establish_connection(:adapter => 'jdbcmysql', :database => 'mydb' , :host => 'localhost', :username => 'root', :password => 'root' )
end
def getSqlServer
$record = MysqlConnection.connection.select_all('SELECT * from Installation')
end
end
dbp = Databaseoperation.new
dbp.mysqlConnect
Error message:
ActiveRecord::ConnectionNotEstablished: ActiveRecord::ConnectionNotEstablished
retrieve_connection at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/connection_pool.rb:546
retrieve_connection at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/connection_handling.rb:79
connection at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/connection_handling.rb:53
columns at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/model_schema.rb:208
column_names at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/model_schema.rb:247
define_attribute_methods at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/attribute_methods.rb:29
synchronize at org/jruby/ext/thread/Mutex.java:149
define_attribute_methods at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/attribute_methods.rb:26
method_missing at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/attribute_methods.rb:123
mysqlConnect at ./databaseoperation.rb:12
(root) at ./databaseoperation.rb:23
If I don't put my statements inside methods in my class it connects to the database. But I really would like to be able to have connections and sql statements separated in methods for my class. How can I do this? Note that I'm using jruby-1.7.4.

net-ssh and ActiveRecord 3: bringing it all together

I'm working on a small Ruby program that will connect to a remote MySQL Bugzilla database, perform a query of records, and email details of those records to a group on a daily basis.
So far, I've been able to SSH to the db server and execute a command using net-ssh. Here's an example:
require 'net/ssh'
Net::SSH.start("db.example.com", "sroach", :password => "secret") do |ssh|
result = ssh.exec!("ls -l")
puts result
end
That outputs just fine.
Using ActiveRecord 3.0.3, I wanted to test the establish_connection method so I established a connection to my local MySQL database and was able to execute commands using ActiveRecord. Example:
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "localhost",
:database => "list_tool_development",
:username => "my_username",
:password => "secretpassword"
)
class MailingList < ActiveRecord::Base
end
MailingList.first #=> Successfully retrieves first record from the table
So, where I'm having trouble is bringing it all together and applying it to my remote MySQL db. Here's my best try thus far:
require 'net/ssh'
Net::SSH.start("db.example.com", "sroach", :password => "secret") do |ssh|
ssh.forward.local(3307, "127.0.0.1", 3306)
ssh.loop { true }
end
But all that does is make my IRB session hang (which could be completely normal...don't know). Incase that hang was normal, I opened a new IRB session and tried to establish a connection to the remote database like so:
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "127.0.0.1",
:port => 3307,
:reconnect => false,
:database => "bugs",
:pool => 5,
:username => "my_username",
:password => "secret",
:socket => "/tmp/mysql.sock"
)
class Bug < ActiveRecord::Base #=> the table name in the "bugs" db is "bugs"
end #=> so I made the model singular
Bug.first #=> the IRB session hangs at this point
So, I have no idea what's going wrong or how to degub it. Any and all suggestions would be helpful.
I'm on Mac OSX. The db that I'm trying to connect to is on FreeBSD 7.0 and is MySQL version Ver 14.12 Distrib 5.0.67.
Rather than try to tunnel the ActiveRecord connection inside SSH, have you tried connecting directly from ActiveRecord to the DB server? That is the normal way to connect across a network and is directly supported by ActiveRecord.
Replace the host ID with the server host IP or DNS entry, the port can probably be allowed to default to the MySQL driver's default of 3306, and the socket isn't needed since the DB is on the remote host.
If the DB host isn't on the same network as yours, and you're crossing firewalls, you might need to have that port opened to allow the connection. If it is on the same network it should work without needing ssh at all.

Resources