Thread send mail in Ruby - ruby-on-rails

I'am new in ruby and i want to send mail every days at 9PM with data so any ideas to do this in ruby ( Thread )
this my code to send mail :
message = <<MESSAGE_END
From: TEST <test#test.com>
To: A Test User <tes2t#test.com>
Subject: Feedback mail status reminder
This is a test e-mail message.
MESSAGE_END
Net::SMTP.start('localhost') do |smtp|
smtp.send_message message, 'test#test.com',
'test2#test.com'
end
Thanks

Sidekiq is also a better option to do it. You can run your job at specific timings and it will run using redis server in the backgorund.
Create Workers in 'app/' folder and call it from the controller/Model method. Setup an initializer file sidekiq.rb to specify the Redis queue for all environments to boot up.
Check the below given links for reference.
https://github.com/mperham/sidekiq
http://sidekiq.org/
http://railscasts.com/episodes/366-sidekiq
Hope it helps.

you can use the gem 'whenever', like this:
every :day, :at => '12:00am' do
runner "AAA.xxx"
end
and your code:
message = <<MESSAGE_END
From: TEST
To: A Test User
Subject: Feedback mail status reminder
This is a test e-mail message.
MESSAGE_END
as a method xxx

In ruby on rails, maybe you can use rufus-scheduler. Create a rb file under config\initializers. Add some code like:
scheduler.cron '0 21 * * *' do
# call your function method or implment the function
end
For more detail, please refer to rufus-scheduler

Related

How to run heroku restart from inside of a rails app?

I understand that from the console I can run heroku restart. What I'd like to do is to have a button in my app (admin console), where pushing that button runs a heroku restart. Does anyone know how to do that and if it's possible? So the code would look something like this:
<button id="heroku_restart">Restart</button>
$("#heroku_restart").click(function() {
$.post('/restart', {}).done(function(response) {
alert(response)
})
})
class AdminsController
# this is the action mapped to the route /restart
def restart
# code for heroku restart
end
end
So per #vpibano, as of this writing, doing it with the platform-api is a breeze. Here's the action POSTed to by a button on my website:
def restart
heroku = PlatformAPI.connect_oauth(ENV["heroku_oauth_token"])
heroku.dyno.restart_all("lastmingear")
render nothing: true
end
As per the description mentioned in the post, the one way of doing it is :
1) First locate the server.pid file
pid_file = Rails.root.join("tmp", "pids", "server.opid")
2) Now, truncate the contents of the file
File.open(pid_file, "w") {|f| f.truncate(0)}
3) Finally, run the server using Kernel module:
Kernel.exec("rails s")
Note: As rightly, mentioned by #vpibano you will need authentication to access your app.
This is not a working model but a way to achieve the requirement.
Hope it helps!!

Publish a Sidekiq schedule job through Private Pub in rails

I am using 'Sidekiq' to schedule reminder about any task on given time. Its working perfect. Now i want to append it to notify on my navbar, for it i am using 'Private Pub' to publish the reminder message.
Here is code of Sidekiq Worker.
class ReminderWorker
include Sidekiq::Worker
def perform(args)
reminder = Reminder.find(args['id'])
reminder.activate = true
PrivatePub.publish_to("reminder", message: reminder)
reminder.save
end
end
and inside "application.js" i am using alert for testing but it is not working.
PrivatePub.subscribe("reminder", function(data, channel) {
return alert('Remarks ='+ data.message.remarks);
});
Am i missing some thing? As it is possible to publish data through Private Pub in rb file accourding to Ryan http://railscasts.com/episodes/316-private-pub?autoplay=true
This gem has been updated last time three years ago and seems not maintained.
Maybe it's better to use newest rails solution like ActionCabble? https://github.com/rails/rails/tree/master/actioncable
I found this issue, that proofs that ActionCabble can be integrated to ActiveJob or other background workers:
https://github.com/rails/rails/issues/22897

Stubbing instance method for OpenTok object

The gem I'm using to integrate OpenTok in my Rails application is at: https://github.com/opentok/Opentok-Ruby-SDK. I based the core of the application on this example: http://www.tokbox.com/blog/building-a-video-party-app-with-ruby-on-rails.
In the relevant part of code, I'm creating an #opentok object in the config_opentok method:
def config_opentok
if #api_key.nil? or #api_secret.nil?
if Rails.env.development?
#api_key = API_KEY
#api_secret = API_SECRET
else
#api_key = ENV['API_KEY']
#api_secret = ENV['API_SECRET']
end
end
if #opentok.nil?
#opentok = OpenTok::OpenTokSDK.new(#api_key, #api_secret)
end
end
And I'm creating a session with the following code:
config_opentok
if Rails.env.development?
session = #opentok.create_session('localhost')
else
session = #opentok.create_session(request.remote_addr)
end
The trouble is, the create_session seems to throw an error
SocketError: getaddrinfo: nodename nor servname provided, or not known
whenever I run my Rspec tests without an internet connection. So I'd like to stub that method so that it returns just a hash {:sessionId => 1}. But I'm having trouble figuring out how to stub the method. I can't just stub the OpenTok module or the OpenTok::OpenTokSDK class. How would I go about stubbing the create_session method?
here's what I've been doing that works:
First, what I tend to do is to initialize the OpenTok object when the app loads so I'm not creating an OpenTok object on every request. To do this, I create a ruby file (apis.rb) in my config/initializers folder.
My apis.rb looks like this:
TB_KEY = ENV['TB_KEY']
TB_SECRET = ENV['TB_SECRET']
OTSDK = OpenTok::OpenTokSDK.new TB_KEY, TB_SECRET
In my controller, to generate a session I'll simply call OTSDK.createSession, similar to what you already have.
To test with rspec, you can simply write in your test file:
OTSDK.stub(:createSession).and_return( {:sessionId => "1MX_2A3453095J0TJ30..."} )
If you run rspec with wifi turned off calling createSession should no longer throw an error.
Here's the documentation for rspec stubbing: http://rubydoc.info/gems/rspec-mocks/frames
Good Luck!
The trouble is, the create_session seems to throw an error whenever I run my Rspec tests without an internet connection.
Instead of attempting to stub, why not give your tests a mock internet connection with VCR?
After initial set up, VCR lets you run all of your tests as if you were actively connected to the internet. This allows you to run tests offline, speeds up all the tests that needed an active connection, and gives you a consistent set of results.
If you have a subscription to RailsCasts, Ryan made a video about VCR in episode 291

How can I get delayed_job to log application output?

I have added the following code to my initializers:
require 'delayed/worker'
Delayed::Worker.logger = ActiveSupport::BufferedLogger.new("log/#{Rails.env}_delayed_jobs.log", Rails.logger.level)
module Delayed
class Worker
def say_with_flushing(text, level = Logger::INFO)
if logger
say_without_flushing(text, level)
logger.flush
end
end
alias_method_chain :say, :flushing
end
end
But it only seems to output stuff like:
2011-09-06T14:02:04-0700: [Worker(delayed_job host:Caribbean.local pid:80322)] 1 jobs processed at 16.5391 j/s, 0 failed ...
2011-09-06T14:03:19-0700: [Worker(delayed_job host:Caribbean.local pid:80322)] MailTest completed after 0.2072
...
Is there a way to get it to actually output what it's doing? Ideally what I am trying to get is the actual outgoing email content that would normally be seen in development mode, but have it go into the delayed_job.log (regardless of rails environment).
So without having mailing go through delayed_job, in production mode the output in the log is something like:
[Mail sent to foo#foo.com]
But I want to get the actual contents as they'd be displayed if I were in development mode-- (the entire email body, subject, etc) but again in the delayed_job log because delayed_job is handling mailing emails.

Working with Starling and multiple instances of Mongrel through Mongrel Cluster

Situation:
In a typical cluster setup, I have a 5 instances of mongrel running behind Apache 2.
In one of my initializer files, I schedule a cron task using Rufus::Scheduler which basically sends out a couple of emails.
Problem:
The task runs 5 times, once for each mongrel instance and each recipient ends up getting 5 mails (despite the fact I store logs of each sent mail and check the log before sending). Is it possible that since all 5 instances run the task at exact same time, they end up reading the email logs before they are written?
I am looking for a solution that will make the tasks run only once. I also have a Starling daemon up and running which can be utilized.
The rooster rails plugin specifically addresses your issue. It uses rufus-scheduler and ensures the environment is loaded only once.
The way I am doing it right now:
Try to open a file in exclusive locked mode
When lock is acquired, check for messages in Starling
If message exists, other process has already scheduled the job
Set the message again to the queue and exit.
If message is not found, schedule the job, set the message and exit
Here is the code that does it:
starling = MemCache.new("#{Settings[:starling][:host]}:#{Settings[:starling][:port]}")
mutex_filename = "#{RAILS_ROOT}/config/file.lock"
scheduler = Rufus::Scheduler.start_new
# The filelock method, taken from Ruby Cookbook
# This will ensure unblocking of the files
def flock(file, mode)
success = file.flock(mode)
if success
begin
yield file
ensure
file.flock(File::LOCK_UN)
end
end
return success
end
# open_lock method, taken from Ruby Cookbook
# This will create and hold the locks
def open_lock(filename, openmode = "r", lockmode = nil)
if openmode == 'r' || openmode == 'rb'
lockmode ||= File::LOCK_SH
else
lockmode ||= File::LOCK_EX
end
value = nil
# Kernerl's open method, gives IO Object, in our case, a file
open(filename, openmode) do |f|
flock(f, lockmode) do
begin
value = yield f
ensure
f.flock(File::LOCK_UN) # Comment this line out on Windows.
end
end
return value
end
end
# The actual scheduler
open_lock(mutex_filename, 'r+') do |f|
puts f.read
digest_schedule_message = starling.get("digest_scheduler")
if digest_schedule_message
puts "Found digest message in Starling. Releasing lock. '#{Time.now}'"
puts "Message: #{digest_schedule_message.inspect}"
# Read the message and set it back, so that other processes can read it too
starling.set "digest_scheduler", digest_schedule_message
else
# Schedule job
puts "Scheduling digest emails now. '#{Time.now}'"
scheduler.cron("0 9 * * *") do
puts "Begin sending digests..."
WeeklyDigest.new.send_digest!
puts "Done sending digests."
end
# Add message in queue
puts "Done Scheduling. Sending the message to Starling. '#{Time.now}'"
starling.set "digest_scheduler", :date => Date.today
end
end
# Sleep will ensure all instances have gone thorugh their wait-acquire lock-schedule(or not) cycle
# This will ensure that on next reboot, starling won't have any stale messages
puts "Waiting to clear digest messages from Starling."
sleep(20)
puts "All digest messages cleared, proceeding with boot."
starling.get("digest_scheduler")
Why dont you use mod_passenger (phusion)? I moved from mongrel to phusion and it worked perfect (with a timeamount of < 5 minutes)!

Resources