Pick up rails environment when running whenever - ruby-on-rails

I need to parameterize some of my cron tasks that I'm generating with whenever by values that I usually access with the rails config gem. So I want to do something like:
every 2.hours do
execute 'my/command/with/parameter #{Settings.parameter}'
end
When I try to do this I get:
config/schedule.rb:14:in `initialize': uninitialized constant Whenever::JobList::Settings (NameError)
So I conclude that whenever doesn't run in the Rails environment, which is a shame as I'd like to do some cooler stuff with it (schedule stuff based on the DB state after running rake db:seed, for example). Is there any way to get the whenever to run in the Rails context?

Rails comes with "runner" which allows a non-web-stack script to have access to the Rails app's environment and configuration. It's tailor made for this sort of task.

Related

Rake task during application initialization rails

I want to execute a rake task when the server of my application starts.
In config/application.rb i put the following:
if !Rails.env.production?
Rake::Task[ "init:db_records" ].invoke
end
The rake task is well defined, and runs without a problem if i invode it from terminal
rake init:db_records
But when placed in config/application.rb (or even in any initializers/*) i got the following error.
Don't know how to build task 'init:db_records'
What is the way to execute a rake task when the server starts ?
Thanks!
Rails already has a mechanism for setting up a development database -- rake db:seed. It does not run automatically when you start the app, but it does run as part of rake db:setup.
Unless you have a good reason, it's usually best to stick the conventions that Rails provides.
For those who encounter the same problem in the future.
I achieved this by creating a new file in the initializers directory, where i put the code of the rake task.
The advantage of this at this point, is that the application is already loaded, so you have access to ActiveRecord functions...
Putting the code directly in config/application.rb didn't work, since my models were not loaded yet.
Hope it will help!
Your Rake tasks are (likely) defined in a Rakefile. The initializer has no idea that file even exists, so it doesn't know about the tasks within.
The easiest way to circumvent this is by doing something like this:
Dir.chdir(Rails.root) do
`rake init:db_records`
end
That is, change the working directory to the root rails directory, then running the command.

How to write and execute an individual rake task outside the Rails application folder

How do you write a rake task outside the Rails application directory and make it run.
For example, say write a sample rake task
task :dummy do
puts User.first.first_name
end
this task is under ~/fun/sample.rake
And my rails application is located at ~/my_app/
Now I need to run the sample.rake. I know i need to load the environment, DB etc., etc., how do i do that? Stuck at this for the past hour.
I tried the one below, obviously it did not work because it did not know how to build it.
rake -f ~/my_app/Rakefile dummy
Note: I should not touch the files inside the Rails application but I can write whatever I want inside the fun directory
You need to create a Rakefile and load the rake gem. See this answer: Ruby: Accessing rake task from a gem without Rails

How to tell when Rails app is activated by migration?

I'm trying to create a migration for my app, and in this app I'm using a gem that tries to startup a different service upon app startup. Apparently, creating a migration...
rails generate migration AddSomeStuffToTable stuff:string
...activates the app, and this gem which tries to connect to startup the service. It appears that starting up the app via generating a migration makes the service startup unable to connect, so it just keeps sleeping and trying again, never actually running the migration.
In this gem, I've already dealt with this for rake, so this is what I've got so far:
MyService.start unless defined? Rake or defined? IRB
This handles the rake problem (like rake db:migrate, rake db:populate), but how can I handle the creation of migration, which (as far as I know) is not a Rake task?
You could try using environment variables for disabling the service:
MyService.start unless ENV['NO_SERVICE']
And run your command like this:
NO_SERVICE=1 rails generate migration AddSomeStuffToTable stuff:string
However, I doubt this scales well, especially if multiple developers are in the app. A better approach might be to do the reverse of this, to only start the service if a particular env variable is present. However, going this direction, you'd need to make sure your app servers set this variable, for example:
Apache: SetEnv START_SERVICE 1
nginx: env START_SERVICE=1
thin: START_SERVICE=1 thin start

Rails 3 Create Script to Manipulate My DB

I'm trying to create a script to mess around with the db entries in my rails application, but I don't know how to properly set it up to gain access to all my models etc.
I can do this easily with scripts like seeds.rb using 'rake db:seed' to execute or in my application controllers, but I want to create scripts outside of these that I can run in the background or just once.
Do I need to include something, or call the script with a certain rails command? And as a second related question, is there any way for me to execute rails commands like 'rake db:seed' from within a ruby script? The only method I know of right now that works is running 'rails console' and executing commands there.
require 'config/environment.rb'
When the script is in your rails root...

Execute db:migrate and db:setup rake tasks inside a controller using jruby and warble

I'm creating an app that must allow the non-programmer end user to install the application by himself.
I already handled the ruby env + web server + database installation part. Now I have to be able to setup the database for the app. I'm thinking about running rake db:setup inside a InstallationController (which will be only accessible during the installation process).
Is it possible? How can I do that?
I'm planning to use Warble and JRuby, so I won't be able to do it by using the command-line inside my app.
As long as the database exists (or creates on use like sqlite3) you can throw an initializer in your app to run the migrations pretty easily.
ActiveRecord::Migrator.migrate(Rails.root.join('db','migrate'))
You won't be able to use the controller if the database is not properly set. If the setup has to be through a web interface you can include a small Sinatra application that takes care of the DB creation, migrations, etc. To do it you only have to shell out your commands (you can do it by backquoting the command):
puts "Migrating database..."
`rake db:migrate`

Resources