I have an instance variable #balance = 300 that I would like to automatically add 300 to its value each month (or 30 days). How would I go about doing this in rails?
You can use a scheduler, sidekiq or cron job, if you are using heroku then there is an easy scheduler call heroku scheduler.
Just make a rake task with code like this:
if Time.now.day == 1
#balance += 300
end
And set the scheduler to use this task everyday. If you are not using heroku, then you will have to implement a cron job.
I suggest storing it somewhere in the database, using a gem like
sidekiq
Railscast for it
or
https://www.ruby-toolbox.com/categories/Background_Jobs
Any of these.
Related
I am pre-storing records in a table A and I want to transfer these records from table A to table B automatically at a specific time, lets say on every evening at 08:00 PM.
Any ideas on how to solve this little problem?
You could create rake task to implement your job, and then schedule it with cron, default *nix time manager. Its syntax is difficult to remember, so I prefer to use Ruby wrapper around it, gem whenever.
You can use whenever gem to run cron jobs ...for example job that runs every 5 mins
in schedule.rb
every 5.minutes do
rake "transfer_data:send_data"
end
lib/tasks/send_data.rake
#!/usr/bin/env ruby
namespace :transfer_data do
desc "Rake task to transfer data
task :send_data => :environment do
## code to transfer data from one table to other table
end
end
Execute the task using bundle exec rake transfer_data:send_data
I want to schedule daily reports to subscribed users via email.
For that I have written action in reports_controller that fetch data from database & convert it into pdf using pdfkit/wkhtmltopdf.The action works fine when called from get request.But when converted so that be defined like
def self.dailymail
ac = ActionController::Base.new()
kit = PDFKit.new #retrieve data from db
pdf = kit.to_pdf
ReportMailer.send_reports(ac.send_data(pdf)).deliver
end
It raises exception at send_data call when used with rufus scheduler:
RackDelegation#content_type= delegated to #_response.content_type=, but #_response is nil: #<ActionController::Base:0x206b068 #_routes=nil, #_action_has_layout=true, #_headers={"Content-Type"=>"text/html"}, ...
so, my question is what how can I solve this problem or Is there any alternate scheduler in rails that work fair on both Windows and Linux?
I wish to know any scheduler that can be helpful to send reports fetched from database.
I agree with claasz regarding the rake task. Check out the whenever gem https://github.com/javan/whenever
There is no suport for windows Task Scheduler, but it does support creating cron jobs.
Check out the documentation for the details, but esentially the gem creates cron jobs based on what you configure in the schedule.rb file that is created when you install the gem.
sample content of schedule.rb:
every 3.hours do
runner "MyModel.some_process"
rake "my:rake:task"
command "/usr/bin/my_great_command"
end
This would be like running bundle exec rake my:rake:task every 3 hours
After creating the schedule.rb you will need to run the whenever command from the console in order to add your schedule to cron. If you run whenever without arguments, the output shows you the contents of the schedule.rb. There is an argument you need to provide that I can't remember off the top of my head, just pass --help and I think you'll get the answer.
Hope this helps
EDIT:The argument is -w to write to cron-tab
As willglynn already points out, you should get rid of any controller interaction. There's simply no need here and it makes things unnecessarily complicated. So your code should look more like
def self.dailymail
kit = PDFKit.new #retrieve data from db
pdf = kit.to_pdf
ReportMailer.send_reports(pdf).deliver
end
If you got problems with the rufus scheduler (which I don't know), you could create a rake task to send out your mails and use the OS scheduler (e.g. cron on Linux) to call the task. Having the rake task would be also convenient for testing.
I need to automatically change a record in my database on a specific date and time.
Example: When the date and time is 01/12/2012 17:15:00 I want some record to automatically be set to 1. Is there any solution to this?
(I am using Rails 3.2.6)
Update 30.11.12 - 13:06
The real problem is that I have a datetime record in my database, when the date and time in this record exceeds todays date and time - then I want another record to be set to 1. Is there any way I can make an if statement, or something, somewhere in my controller?
I can see a few possible options here. It depends on your assumptions/constraints.
Possible assumptions (ordered by increasing difficulty to implement):
1) the data does not need to be correct in the database, but the next time somebody takes a look at the data, we fix it accordingly
2) the data does not need to be correct in the database, but e.g. within a definable time-interval
3) the data needs to be correct in the database at all times
Let me go over these in more detail
The data will appear correct, next time somebody looks at the data
This is actually pretty easy. When retrieving the data to be shown, then check if certain conditions/times have past, and set flags accordingly.
For the user it is actually not relevant when the flags were set correctly, but everytime a user will look at the data, the flags will be set correctly.
The data will be correct inside a given time-interval
A simple case is to check every hour, every half hour, once per day and set or fix the states of items that need to be changed.
To accomplish this you would use a cron job or a gem like whenever
This is a very simple approach and will assure your data will be correct in an acceptable/given interval (if your problem has such an interval of course).
The data must be set at the correct time
Here I see two options, either for each item that needs to change state at a given time, schedule a
task using the same options as before: cron or the whenever gem. This would work, but I am not entirely sure if cron is the best solution for scheduling a lot of 1-off jobs.
Alternatively, a very clean solution is to use a gem like DelayedJob. This gem is mostly used to offload tasks to the background, e.g. for tasks that need a bit more time processin. But you can also use it to execute tasks in the near future, at a very specific time.
def change_flag_when_needed
# change the flag
end
# 5.minutes.from_now will be evaluated when change_flag_when_needed is called
handle_asynchronously :in_the_future, :run_at => Proc.new { 5.minutes.from_now }
Whenever you will call change_flag_when_needed, it will evaluate the given block, which now contains 5.minutes.from_now, but could as well calculate the actual time when it should be performed.
Hope this helps.
You could use whenever https://github.com/javan/whenever to set up a cron job for you
Whenever has an easy syntax in its schedule.rb file to let you run tasks "whenever" you like
From their readme:
every 3.hours do
runner "MyModel.some_process"
rake "my:rake:task"
command "/usr/bin/my_great_command"
end
every 1.day, :at => '4:30 am' do
runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end
every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
runner "SomeModel.ladeeda"
end
every :sunday, :at => '12pm' do # Use any day of the week or :weekend, :weekday
runner "Task.do_something_great"
end
every '0 0 27-31 * *' do
command "echo 'you can use raw cron syntax too'"
end
# run this task only on servers with the :app role in Capistrano
# see Capistrano roles section below
every :day, :at => '12:20am', :roles => [:app] do
rake "app_server:task"
end
use cron job on linux server and set time for run script
In my application, I need to execute a task every 5 minutes. The task itself is quite lean, so that's not the problem: the point is that loading the Rails environment uses almost all the CPU of the server. Right now, I'm using whenever with a code like this in my schedule.rb:
every 5.minutes do
runner Task.perform
end
But the cost is too big. Is there anyway to execute this kind of tasks in a preloaded environment? Or any other better solution?
Consider using a background process (many gems, notably delayed job) and implementing a simple "cron" in your code with a polling loop something like
def perform
last = Time.now
while true
if last.sec % (5 * 60) != 0
do_task
last = Time.now
end
end
end
Warning: this example has more holes than a slice of swiss cheese. Write something better :-)
You could use a cron job or set it up to run in a bash script. These would have the advantage of not being tied to your application.
i have a job to update some information in db every midnight ,so i want to find a way can use rails model to update information to db,
what's the common soluation?
Use a cron job which then runs a rake task. Define the task like this in _lib/tasks/your_thing.rake_:
task :your_thing => :environment do
# do stuff
end
Delayed Job https://github.com/tobi/delayed_job
Resque https://github.com/blog/542-introducing-resque