Why does my Ruby program not initialize multiple database connections? - ruby

I have an issue with my database connections overwriting each other.
I create two individual connections, but when I call $db1.execute_sql, $db2.execute_sql is actually what gets called.
Here is what I have:
servers.yml:
db1:
adapter: jdbc
driver: oracle.jdbc.driver.OracleDriver
url: db_1_url
username: my_username
password: m_password
db2:
adapter: jdbc
driver: oracle.jdbc.driver.OracleDriver
url: db_2_url
username: my_username
password: m_password
ServerContext class:
class ServerContext
def initialize (env)
connect(env)
end
def connect(env)
begin
config = YAML.load_file("features/config/servers.yml")
rescue
puts "cannot load config/servers.yml"
end
#connection = ActiveRecord::Base
#connection.establish_connection(config[env])
end
def execute_sql(sql_string)
#connection.connection.execute(sql_string)
end
Database setup:
def connect_databases
$db1 = ServerContext.new('db1')
$db2 = ServerContext.new('db2')
end

The current connection is a thread local variable so you can only set it to one thing at a time - http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html
You need two separate classes that inherit from ActiveRecord::Base to do what you want

You're doing
#connection = ActiveRecord::Base
I think as you're using the same static method of the class two times for the connection, the second time it simply rewrites the previous connection.
Create a class that extends from ActiveRecord::Base for each connection:
class DB1 < ActiveRecord::Base
self.abstract_class = true
end
class DB2 < ActiveRecord::Base
self.abstract_class = true
end
Then, in your connect method:
case config[env]
when 'db1'
#connection = DB1
when 'db2'
#connection = DB2
end

So the new activeRecord stores connections in a hash based on Class name. So each time I was overwriting the connection in ActiveRecord (not in the class itself). See http://api.rubyonrails.org/classes/ActiveRecord/Base.html and look under Connection to multiple databases in different models.

Related

Mailer unable to access reset_token in User model

faced with an issue where #user.reset_token returns nil.
app/views/user_mailer/password_reset.html.erb
<%= link_to "Reset password", edit_password_reset_url(#user.reset_token, email: #user.email) %>
Reset_token is declared in User model, whereby this problem happens when I try to use a sidekiq worker. Refer to code below.
app/models/user.rb
class User < ActiveRecord::Base
attr_accessor :reset_token
def User.new_token
SecureRandom.urlsafe_base64
end
def send_password_reset_email
PasswordResetWorker.perform_async(self.id)
end
private
def create_reset_digest
self.reset_token = User.new_token
update_attribute(:reset_digest, User.digest(reset_token))
update_attribute(:reset_sent_at, Time.zone.now)
end
app/workers/password_reset_worker.rb
class PasswordResetWorker
include Sidekiq::Worker
sidekiq_options retry: false
def perform(user_id)
user = User.find(user_id)
UserMailer.password_reset(user).deliver
end
end
app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default from: "noreply#example.com"
def password_reset(user)
#user = user
mail to: user.email, subject: "Password Reset"
end
end
This problem DOES NOT happen when I do not use workers
app/models/user.rb
def send_password_reset_email
UserMailer.password_reset(self).deliver
end
Would like to know what can I replace "#user.reset_token" with? Let me know if you need more info. Thanks in advance.
You're not storing the reset_token in the database - you're storing the reset_digest.
When you don't use workers, you're storing the reset_token in the User instance, then passing that same User instance to your mailer - hence the reset_token is still available.
When you use workers, your worker only has the User's ID, so it's reloading the User instance from the database. Because the reset_token isn't being stored in the database, it's coming back nil.
Either you should be saving the reset_token in the database, or your password email should be using reset_digest in the URL.

ActiveRecord connection establishing, but why is it not connected

I'm in the process of updating ActiveRecord on my ruby suite (a much needed upgrade) and I'm running into an issue with the database connections. It doesn't seem to fail on the ActiveRecord::Base.establish_connection call, however when I puts the connected? method it returns false. I've included the hash i'm passing into the establish_connection method (subbing out the url, username, and password that I've verified work) and my connected? call
puts "establishing connection to #{config[env]}"
#db_connection = ActiveRecord::Base.establish_connection(config[env])
puts "database connected? #{#db_connection.connected?}"
OUTPUT:
establishing connection to {"adapter"=>"jdbc", "driver"=>"oracle.jdbc.driver.OracleDriver", "url"=>"my_url","username"=>"my_username", "password"=>"my_password"}
database connected? false
EDIT: connect method
def connect(env)
begin
config = YAML.load_file("features/config/servers.yml")
rescue
puts "cannot load config/servers.yml"
end
puts "establishing connection to #{config[env]}"
#db_connection = ActiveRecord::Base.establish_connection(config[env])
puts #db_connection.connected?
puts "connected to #{config[env]}"
end
Database YML
adapter: jdbc
driver: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=host_ip_address)(PORT=host_port_number))(CONNECT_DATA=(UR=A)(SERVICE_NAME=database_name)))
username: my_username
password: My_Password

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.

Ruby ActiveRecord Dynamic Model creation

I am trying to establish a multiple DB connection with ActiveRecord.Currently I need to insert data into total 2 Databases. There is a possibility for increase in the No.Of databases.
So I created 2 classes dynamically which will Extend from ActiveRecord::Base
Object.const_set("Connection1",Class.new(ActiveRecord::Base) do
self.abstract_class = true
self.establish_connection({
:host=>"localhost", :username=>"root", :password=>"root", :database=>"db1", :encoding=>"utf8", :adapter=>"mysql2"})
end)
Object.const_set("Connection2",Class.new(ActiveRecord::Base) do
self.abstract_class = true
self.establish_connection({
:host=>"localhost", :username=>"root", :password=>"root", :database=>"db2", :encoding=>"utf8", :adapter=>"mysql2"})
end)
Then I created Dynamic models extends from each class accordingly
Object.const_set("ConnectionUser1",Class.new(Connection1) do
self.table_name = 'user'
def self.foo
all.count
end
end)
Object.const_set("ConnectionUser2",Class.new(Connection2) do
self.table_name = 'user'
def self.foo
all.count
end
end)
Then when I tried to call foo method
p ConnectionUser1.foo
p ConnectionUser2.foo
It gives me ActiveRecord::ConnectionNotEstablished Error.
I heard that if the model doesn't have connection ActiveRecord will take connection of their parent.
So according to this ConnectionUser1 should use the connection of Connection1 and ConnectionUser2 use the connection of Connection2.
Then why ActiveRecord fails to Establish Connection?
Any help will be appreciated.
Thank you.
Take a look at below link which shows that how to use multiple database with ActiveRecord.
How do i work with two different databases in rails with active records?

Sharing DB connections across objects using class methods in ruby?

I am writing a ruby script to be used as Postfix SMTP access policy delegation. The script needs to access a Tokyo Tyrant database. I am using EventMachine to take care of network connections. EventMachine needs a EventMachine::Connection class that is instantiated by EventMachineā€˜s processing loop whenever a new connection is created. so for each connection a class is instantiated and destroyed.
I am creating a connection to Tokyo Tyrant from the post_init of the EventMachine::Connection (ie right after connection is setup) and tearing it down after connection is terminated.
My question is if this is the proper way to connect to db? ie making a connection every yime I need it and tearing it down after I am finished? Wouldn't be better to connect to DB once (when program is started) tear it down during program shutdown? If that is so how should I code that ?
My code is:
require 'rubygems'
require 'eventmachine'
require 'rufus/tokyo/tyrant'
class LineCounter < EM::Connection
ActionAllow = "action=dunno\n\n"
def post_init
puts "Received a new connection"
#tokyo = Rufus::Tokyo::Tyrant.new('server', 1978)
#data_received = ""
end
def receive_data data
#data_received << data
#data_received.lines do |line|
key = line.split('=')[0]
value = line.split('=')[1]
#reverse_client_name = value.strip() if key == 'reverse_client_name'
#client_address = value.strip() if key == 'client_address'
#tokyo[#client_address] = #reverse_client_name
end
puts #client_address, #reverse_client_name
send_data ActionAllow
end
def unbind
#tokyo.close
end
end
EventMachine::run {
host,port = "127.0.0.1", 9997
EventMachine::start_server host, port, LineCounter
puts "Now accepting connections on address #{host}, port #{port}..."
EventMachine::add_periodic_timer( 10 ) { $stderr.write "*" }
}
with regards,
raj
Surprising there's no answers to this question.
What you probably need is a connection pool where you can fetch, use, and return connections as they are required.
class ConnectionPool
def initialize(&block)
#pool = [ ]
#generator = block
end
def fetch
#pool.shift or #generator and #generator.call
end
def release(handle)
#pool.push(handle)
end
def use
if (block_given?)
handle = fetch
yield(handle)
release(handle)
end
end
end
# Declare a pool with an appropriate connection generator
tokyo_pool = ConnectionPool.new do
Rufus::Tokyo::Tyrant.new('server', 1978)
end
# Fetch/Release cycle
tokyo = tokyo_pool.fetch
tokyo[#client_address] = #reverse_client_name
tokyo_pool.release(tokyo)
# Simple block-method for use
tokyo_pool.use do |tokyo|
tokyo[#client_address] = #reverse_client_name
end

Resources