Ruby on Rails always pointing local redis Server - ruby-on-rails

I am using Redis with my ruby on rails application, To map Ruby object with Redis using redis-objects, dm-core and dm-redis-adapter. Below are the code snipts
Gemfile
gem 'redis-objects'
gem "dm-core", "~> 1.2.1"
gem "dm-redis-adapter"
/config/initializers/redis.rb
// LOCAL REDIS SERVER
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)
// REMOTE REDIS SERVER
#Redis.current = Redis.new(:host => '<VM IP>', :port => <VM PORT>, :password => '<PASSWORD>')
Model.rb
DataMapper.setup(:default, {:adapter => "redis"})
class User
include Redis::Objects
include DataMapper::Resource
include ActiveModel::Validations
include ActiveModel::Conversion
# datamapper fields, just used for .create
property :id, Serial
property :name, String
property :email, String
property :des, Text
def id
1
end
end
User.finalize
It's working fine for local redis server. Why app always pointing local redis, Even when providing remote host and port?
SOLVED: checkout my answer.

As per Question:
// LOCAL REDIS SERVER
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)
// REMOTE REDIS SERVER
#Redis.current = Redis.new(:host => '<VM IP>', :port => <VM PORT>, :password => '<PASSWORD>')
Model.rb
DataMapper.setup(:default, {:adapter => "redis"})
In above code, I am overloading Redis configuration in User model.
In that case, I need to write remote configuration in model as well.
DataMapper.setup(:default, {:adapter => "redis", :host => '<VM IP>', :port => <VM PORT>, :password => '<PASSWORD>'})

Redis.current is a method which always gives a new connection if the instance variable #current is empty. See https://github.com/redis/redis-rb/blob/master/lib/redis.rb#L19
def self.current
#current ||= Redis.new
end
Try assigning Redis.new to some other global like $redis. This should mostly fix your issue.

Related

Load rails app config from database

I'd like to load some config settings from the database when my Rails (3.2.13) app starts:
class MyApp < Rails::Application
#...normal config here...
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => SystemSetting.system_smtp_host,
:port => SystemSetting.system_smtp_port,
:user_name => SystemSetting.system_smtp_username,
:password => SystemSetting.system_smtp_password,
:authentication => SystemSetting.system_smtp_authentication,
:enable_starttls_auto => SystemSetting.system_smtp_enable_starttls_auto }
end
But it appears that the database config has not been read at this point. I get an error:
ActiveRecord::ConnectionNotEstablished (ActiveRecord::ConnectionNotEstablished)
How can I accomplish this? Either make Rails initialize the database config first, or ... something else?
Regarding practices: Doing stuff like this can be problematic because your application relies on your database to be full when in fact it should support an empty database. Two examples that I can think of are when you try to create a database from scratch (e.g. rake db:setup), or in tests environments.
However, if have no other choice: I would move the mailer initialization to your system_setting.rb or an initializer (where you are guaranteed to have a connection).
config/initializers/load_system_settings.rb
MyApp::Application.config.action_mailer.raise_delivery_errors = true
MyApp::Application.config.action_mailer.delivery_method = :smtp
MyApp::Application.config.action_mailer.smtp_settings = {
:address => SystemSetting.system_smtp_host,
:port => SystemSetting.system_smtp_port,
:user_name => SystemSetting.system_smtp_username,
:password => SystemSetting.system_smtp_password,
:authentication => SystemSetting.system_smtp_authentication,
:enable_starttls_auto => SystemSetting.system_smtp_enable_starttls_auto
}
Manually connect and load values from database.
class Application < Rails::Application
# Set your app path
app_base = 'MY_APPLICATION_PATH'
# Load db configs
db_yml = YAML.load_file("#{app_base}/config/database.yml")["production"]
# Establish db connection
ActiveRecord::Base.establish_connection(:adapter=>db_yml['adapter'], :database=>db_yml['database'], :username=>db_yml['username'], :password=>db_yml['password'])
# load model if not
require "#{app_base}/app/model/system_setting.rb" unless defined?('SystemSetting')
#...normal config here...
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => SystemSetting.system_smtp_host,
:port => SystemSetting.system_smtp_port,
:user_name => SystemSetting.system_smtp_username,
:password => SystemSetting.system_smtp_password,
:authentication => SystemSetting.system_smtp_authentication,
:enable_starttls_auto => SystemSetting.system_smtp_enable_starttls_auto }
#close sql connection after loaded
ActiveRecord::Base.connection.close
end

Is there a way to test an email connection with the email gem?

My rails application uses a Ruby script retrieve an object from my database.
This objet is made of six fields that are:
login
password
server
port
event_type_id
active
Using the mail gem, I'm using these informations to create a new Mail connection using Mail.defaults, like this in my MailConnection model:
def check
begin
puts("Attempting to connect to the specified email server...")
Mail.defaults do
retriever_method :pop3, :address => :server,
:port => :port,
:user_name => :login,
:password => :password,
:enable_ssl => false
end
rescue Exception => msg
puts("Unconnected : #{msg}")
false
else
puts("Connected")
true
end
end
I'm using this method in the Ruby script to check if the connection can be etablished before doing anything, but if I'm using invalid datas, it's still returning 'true' even if the network is unreachable.
I'm all new to Ruby and, I would like to know what's wrong with my function;
Thanks in advance.
I'm a beginner myself but have just been having a look at this.
With net/pop
require 'net/pop'
pop = Net::POP3.new('your.mail.server', optional_port)
pop.start('your_username', 'your_password') #should return an error if it fails
pop.started? #if you want to double check
With the Mail gem
If you'd rather use the Mail gem itself, the connection method in the POP3 retriever lets you get at those same methods by yielding a POP3 object to a block:
Mail.defaults do
retriever_method :pop3, :address => :server,
:port => :port,
:user_name => :login,
:password => :password,
:enable_ssl => false
end
Mail.connection {|pop3| pop3.active? }
You might notice I used started? and active? interchangeably: they are the same POP3 instance method. One is simply aliased to the other.

ActiveRecord::ConnectionNotEstablished error

I have written a rake task to update my database which I am doing by a model. I have called the function of model inside my rake task like this:
get_first_student = Student.get_first_id
I have written the model Student like following:
class Students < ActiveRecord::Base
attr_accessible :id, :roll_num :name, :class
self.table_name = 'students'
if Rails.env == "development"
CONN1 = establish_connection :adapter => "mysql2",
:database => "mydb_dev",
:username => "root",
:password => "" ,
:host => "localhost"
CONN2 = establish_connection :adapter => "mysql2",
:database => "mydb2_dev",
:username => "root",
:password => "",
:host => "1.2.3.4"
else
CONN1 = establish_connection :adapter => "mysql2",
:database => "mydb_prod",
:username => "root",
:password => "" ,
:host => "localhost"
CONN2 = establish_connection :adapter => "mysql2",
:database => "mydb2_prod",
:username => "root",
:password => "" ,
:host => "localhost"
end
def self.get_first_id
p "****"
p CONN1
p "****"
sql = %Q{SELECT MIN(id) FROM mydb.students;}
first_student_id = CONN1.connection.execute(sql).first[0]
return first_student_id
end
After running, I am getting this following output:
#<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007f948c223120 #mon_owner=nil,
#mon_count=0, #mon_mutex=#<Mutex:0x007f948c2230d0>, #spec=#
<ActiveRecord::Base::ConnectionSpecification:0x007f948c2232d8 #config=
{:adapter=>"mysql2",:database=>"mydb_dev", :username=>"root", :password=>"",
:host=>"localhost"}, #adapter_method="mysql2_connection">, #reserved_connections={},
#queue=#<MonitorMixin::ConditionVariable:0x007f948c223080 #monitor=#
<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007f948c223120 ...>, #cond=#
<ConditionVariable:0x007f948c223058 #waiters=[], #waiters_mutex=#
<Mutex:0x007f948c223008>>>, #timeout=5, #size=5, #connections=[],
#automatic_reconnect=false>
ActiveRecord::ConnectionNotEstablished
In rails, there are two different adapter for mysql server one in mysql and mysql2 gem. Check if you have mysql gem in your gemfile. If not, then open rails console, and type ActiveRecord::Base.establish_connection("mysql://your_username:yourpassword#localhost/yourdatabasename"). Have you configured your mysql server. Are you getting error in all environments?. Check it by login into mysql server using command 'mysql -u USERNAME -p' by default its root and with not password.
Calling establish_connection the second time has disconnected the first pool you created and that's the CONN1 you're trying to use.
Although this method returns a ConnectionPool object that you can capture and use, it's worth avoiding. ActiveRecord manages the connection pools and unless you explicitly tell it differently will assume you only want one of them active. Recently they've added some nice new ways to manage multiple databases.

Redis-Objects in rails saves as String, not array

I am using the redis-objects gem to store simple info
class Purchase < ActiveRecord::Base
include Redis::Objects
hash_key :user_purchases, :marshal => true, :global => true # "hash" is taken by Ruby
def self.add_user_end(fb_id,item_id)
if self.user_purchases[fb_id]
a = Array.new
a << candidate_id
self.user_purchases[fb_id] = a
else
new_a = self.user_purchases[fb_id]
new_a << item_id
self.user_purchases[fb_id] = new_a
end
end
end
I'm creating a method to collect user_purchases as a hasy_key, keyed by a users fb id. I would imply like to see a collection of ids when I use Purchase.user_purchases["2"] => [1,23,563,2]
I am running into a problem with Redis::Object where I can only save this as a string: Why?
1.9.3-p125 :050 > Purchase.user_purchases["6"].class
=> String
1.9.3-p125 :051 > Purchase.user_purchases["6"]
=> "\u0004\b[\u0006I\"\v543555\u0006:\u0006ET"
Answer:
My Initialization file was missing require 'redis/list'
require 'redis'
require 'redis/objects'
require 'redis/hash_key'
require 'redis/list'
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)
My Initialization file was missing require 'redis/list'
require 'redis'
require 'redis/objects'
require 'redis/hash_key'
require 'redis/list'
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)

How to setup Google Apps with ActionMailer with Rails 2.3.5?

I've got Google Apps setup with email for my domain, and now I need to configure ActionMailer to use it. But the info I've found seems to be conflicting. Can anyone tell me how exactly to set it up with Rails 2.3.5?
I faced the same problems and got it working with this:
Step 1. Add the following to your development environment:
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.default_charset = "utf-8"
ActionMailer::Base.smtp_settings = {
:enable_starttls_auto => true,
:address => "smtp.gmail.com",
:port => "587",
:domain => "domain.com",
:authentication => :plain,
:user_name => "YOUR_USER_NAME", #should be you#domain.com
:password => "YOUR_PASSWORD_HERE"
}
The critical line is :enable_starttls_auto. You have to restart webrick after making changes here.
Step 2. Create a Model like project_mailer.rb
class ProjectMailer < ActionMailer::Base
def confirmation(project)
subject 'Your email subject'
recipients project.email
from 'you#domain.com'
body :project => "hi"
end
end
Step 3. Create a View like /views/project_mailer/confirmation.html.haml (or .erb). This is just a standard view file.
Step 4. Add a line in your controller like:
ProjectMailer.deliver_confirmation(#project)

Resources